Cataclysm DDA
Classes | Public Member Functions | Static Public Member Functions | Public Attributes | Private Member Functions | Static Private Member Functions | List of all members
vehicle Class Reference

A vehicle as a whole with all its components. More...

#include <vehicle.h>

Classes

class  autodrive_controller
 
struct  rackable_vehicle
 
struct  unrackable_vehicle
 

Public Member Functions

std::map< vehicle *, float > search_connected_vehicles ()
 Returns a map of connected vehicle pointers to power loss factor: Keys are vehicles connected by POWER_TRANSFER parts, includes self Values are line loss, 0.01 corresponds to 1% charge loss to wire resistance May load the connected vehicles' submaps Templated to support const and non-const vehicle*. More...
 
std::map< const vehicle *, float > search_connected_vehicles () const
 Returns a map of connected vehicle pointers to power loss factor: Keys are vehicles connected by POWER_TRANSFER parts, includes self Values are line loss, 0.01 corresponds to 1% charge loss to wire resistance May load the connected vehicles' submaps Templated to support const and non-const vehicle*. More...
 
void get_connected_vehicles (std::unordered_set< vehicle * > &dest)
 Returns a map of connected vehicle pointers to power loss factor: Keys are vehicles connected by POWER_TRANSFER parts, includes self Values are line loss, 0.01 corresponds to 1% charge loss to wire resistance May load the connected vehicles' submaps Templated to support const and non-const vehicle*. More...
 
std::map< vpart_reference, float > search_connected_batteries ()
 Returns a map of connected battery references to power loss factor Keys are batteries in vehicles (includes self) connected by POWER_TRANSFER parts Values are line loss, 0.01 corresponds to 1% charge loss to wire resistance May load the connected vehicles' submaps. More...
 
 vehicle (const vproto_id &proto_id)
 
 vehicle (const vehicle &)=delete
 
 ~vehicle ()
 
vehicleoperator= (vehicle &&)=default
 
void suspend_refresh ()
 Disable or enable refresh() ; used to speed up performance when creating a vehicle. More...
 
void enable_refresh ()
 
void refresh (bool remove_fakes=true)
 Refreshes all caches and refinds all parts. More...
 
void refresh_active_item_cache ()
 
safe_reference< vehicleget_safe_reference ()
 Return a pointer-like type that's automatically invalidated if this item is destroyed or assigned-to. More...
 
void set_hp (vehicle_part &pt, int qty, bool keep_degradation, int new_degradation=-1)
 Set stat for part constrained by range [0,durability]. More...
 
bool mod_hp (vehicle_part &pt, int qty)
 Apply damage to part constrained by range [0,durability] possibly destroying it. More...
 
bool player_in_control (const Character &p) const
 
bool remote_controlled (const Character &p) const
 
void init_state (map &placed_on, int init_veh_fuel, int init_veh_status)
 
void smash (map &m, float hp_percent_loss_min=0.1f, float hp_percent_loss_max=1.2f, float percent_of_parts_to_affect=1.0f, point damage_origin=point_zero, float damage_size=0)
 Smashes up a vehicle that has already been placed; used for generating very damaged vehicles. More...
 
void serialize (JsonOut &json) const
 
void deserialize (const JsonObject &data)
 
void deserialize_parts (const JsonArray &data)
 
int print_part_list (const catacurses::window &win, int y1, int max_y, int width, int p, int hl=-1, bool detail=false, bool include_fakes=true) const
 Prints a list of all parts to the screen inside of a boxed window, possibly highlighting a selected one. More...
 
void print_vparts_descs (const catacurses::window &win, int max_y, int width, int p, int &start_at, int &start_limit) const
 Prints a list of descriptions for all parts to the screen inside of a boxed window. More...
 
void invalidate_towing (bool first_vehicle=false, Character *remover=nullptr)
 
void do_towing_move ()
 
bool tow_cable_too_far () const
 
bool no_towing_slack () const
 
bool is_towing () const
 
bool has_tow_attached () const
 
int get_tow_part () const
 
bool is_external_part (const tripoint &part_pt) const
 
bool is_towed () const
 
void set_tow_directions ()
 
bool is_appliance () const
 
bool is_owned_by (const Character &c, bool available_to_take=false) const
 
bool is_old_owner (const Character &c, bool available_to_take=false) const
 
std::string get_owner_name () const
 
void set_old_owner (const faction_id &temp_owner)
 
void remove_old_owner ()
 
void set_owner (const faction_id &new_owner)
 
void set_owner (const Character &c)
 
faction_id get_owner () const
 
faction_id get_old_owner () const
 
bool has_owner () const
 
bool has_old_owner () const
 
bool handle_potential_theft (Character const &you, bool check_only=false, bool prompt=true)
 
std::set< pointimmediate_path (const units::angle &rotate=0_degrees)
 
void autopilot_patrol ()
 
units::angle get_angle_from_targ (const tripoint &targ) const
 
void drive_to_local_target (const tripoint &target, bool follow_protocol)
 
autodrive_result do_autodrive (Character &driver)
 
void stop_autodriving (bool apply_brakes=true)
 
void connect (const tripoint &source_pos, const tripoint &target_pos)
 
bool precollision_check (units::angle &angle, map &here, bool follow_protocol)
 
bool auto_select_fuel (vehicle_part &vp)
 
bool start_engine (vehicle_part &vp)
 
void stop_engines ()
 
void start_engines (bool take_control=false, bool autodrive=false)
 
void backfire (const vehicle_part &vp) const
 
ret_val< void > can_mount (const point &dp, const vpart_info &vpi) const
 
ret_val< void > can_unmount (const vehicle_part &vp_to_remove, bool allow_splits=false) const
 
int install_part (const point &dp, const vpart_id &type)
 
int install_part (const point &dp, const vpart_id &type, item &&base)
 
int install_part (const point &dp, const vpart_id &type, item &&base, std::vector< item > &installed_with)
 
int install_part (const point &dp, vehicle_part &&vp)
 
std::vector< rackable_vehiclefind_vehicles_to_rack (int rack) const
 
std::vector< unrackable_vehiclefind_vehicles_to_unrack (int rack) const
 
bool merge_rackable_vehicle (vehicle *carry_veh, const std::vector< int > &rack_parts)
 
bool merge_vehicle_parts (vehicle *veh)
 
bool merge_appliance_into_grid (vehicle &veh_target)
 
void separate_from_grid (point mount)
 
bool is_powergrid () const
 
bool remove_part (vehicle_part &vp)
 Mark a part as removed from the vehicle. More...
 
bool remove_part (vehicle_part &vp, RemovePartHandler &handler)
 
void part_removal_cleanup ()
 
bool do_remove_part_actual ()
 
bool remove_carried_vehicle (const std::vector< int > &carried_parts, const std::vector< int > &racks)
 
bool find_and_split_vehicles (map &here, std::set< int > exclude)
 
void relocate_passengers (const std::vector< Character * > &passengers) const
 
bool split_vehicles (map &here, const std::vector< std::vector< int >> &new_vehs, const std::vector< vehicle * > &new_vehicles, const std::vector< std::vector< point >> &new_mounts, std::vector< vehicle * > *added_vehicles=nullptr)
 
item_location part_base (int p)
 Get handle for base item of part. More...
 
std::optional< vpart_referenceget_remote_part (const vehicle_part &vp_local) const
 Get the remote vehicle and part that a part is targeting. More...
 
void remove_remote_part (const vehicle_part &vp_local) const
 Remove the part on a targeted remote vehicle that a part is targeting. More...
 
vehicle_part_range get_all_parts () const
 Yields a range containing all parts (including broken ones) that can be iterated over. More...
 
vehicle_part_with_fakes_range get_all_parts_with_fakes (bool with_inactive=false) const
 
std::vector< int > parts_at_relative (const point &dp, bool use_cache, bool include_fake=false) const
 
int part_with_feature (const point &pt, const std::string &f, bool unbroken) const
 Returns index of part at mount point pt which has given f flag. More...
 
int part_with_feature (const point &pt, vpart_bitflags f, bool unbroken) const
 Returns part index at mount point pt which has given f flag. More...
 
int part_with_feature (int p, vpart_bitflags f, bool unbroken) const
 Returns p or part index at mount point pt which has given f flag. More...
 
int avail_part_with_feature (const point &pt, const std::string &f) const
 Returns index of part at mount point pt which has given f flag and is_available(), or -1 if no such part or it's not is_available() More...
 
int avail_part_with_feature (int p, vpart_bitflags f) const
 Returns p or part index at mount point pt which has given f flag and is_available(), or -1 if no such part or it's not is_available() More...
 
int avail_linkable_part (const point &pt, bool to_ports) const
 Returns index of part at mount point pt which has link connection and is_available(), or -1 if no such part or it's not is_available() More...
 
bool has_part (const std::string &flag, bool enabled=false) const
 Check if vehicle has at least one unbroken part with specified flag. More...
 
bool has_part (const tripoint &pos, const std::string &flag, bool enabled=false) const
 Check if vehicle has at least one unbroken part with specified flag. More...
 
std::vector< vehicle_part * > get_parts_at (const tripoint &pos, const std::string &flag, part_status_flag condition)
 Get all enabled, available, unbroken vehicle parts at specified position. More...
 
std::vector< vehicle_part * > get_parts_at (const tripoint_bub_ms &pos, const std::string &flag, part_status_flag condition)
 
std::vector< const vehicle_part * > get_parts_at (const tripoint &pos, const std::string &flag, part_status_flag condition) const
 
bool can_enable (const vehicle_part &pt, bool alert=false) const
 Test if part can be enabled (unbroken, sufficient fuel etc), optionally displaying failures to user. More...
 
int next_part_to_open (int p, bool outside=false) const
 Return the index of the next part to open at p's location. More...
 
int next_part_to_close (int p, bool outside=false) const
 Return the index of the next part to close at p More...
 
int next_part_to_lock (int p, bool outside=false) const
 Return the index of the next part to lock at part p's location. More...
 
int next_part_to_unlock (int p, bool outside=false) const
 Return the index of the next part to unlock at part p's location. More...
 
std::vector< int > all_parts_at_location (const std::string &location) const
 Returns all parts in the vehicle that exist in the given location slot. More...
 
int get_next_shifted_index (int original_index, Character &you) const
 
std::vector< std::vector< int > > find_lines_of_parts (int part, const std::string &flag) const
 Returns all parts in the vehicle that have the specified flag in their vpinfo and are on the same X-axis or Y-axis as the input part and are contiguous with each other. More...
 
point coord_translate (const point &p) const
 
void coord_translate (const units::angle &dir, const point &pivot, const point &p, tripoint &q) const
 
void coord_translate (tileray tdir, const point &pivot, const point &p, tripoint &q) const
 
tripoint mount_to_tripoint (const point &mount) const
 
tripoint mount_to_tripoint (const point &mount, const point &offset) const
 
int part_at (const point &dp) const
 
int part_displayed_at (const point &dp, bool include_fake=false, bool below_roof=true, bool roof=true) const
 Returns which part (as an index into the parts list) is the one that will be displayed for the given square. More...
 
int roof_at_part (int p) const
 
int index_of_part (const vehicle_part *part, bool include_removed=false) const
 
vpart_display get_display_of_tile (const point &dp, bool rotate=true, bool include_fake=true, bool below_roof=true, bool roof=true) const
 
std::vector< itype_idget_printable_fuel_types () const
 Returns an array of fuel types that can be printed. More...
 
void print_fuel_indicators (const catacurses::window &win, const point &, int start_index=0, bool fullsize=false, bool verbose=false, bool desc=false, bool isHorizontal=false)
 Prints all of the fuel indicators of the vehicle. More...
 
void print_speed_gauge (const catacurses::window &win, const point &, int spacing=0) const
 Vehicle speed gauge. More...
 
void precalc_mounts (int idir, const units::angle &dir, const point &pivot)
 
std::vector< int > boarded_parts () const
 
std::vector< rider_dataget_riders () const
 
bool is_passenger (Character &c) const
 
Characterget_passenger (int you) const
 
monsterget_monster (int p) const
 
bool enclosed_at (const tripoint &pos)
 
tripoint_abs_ms global_square_location () const
 
tripoint_abs_omt global_omt_location () const
 
tripoint global_pos3 () const
 
tripoint_bub_ms pos_bub () const
 
tripoint global_part_pos3 (const int &index) const
 Get the coordinates of the studied part of the vehicle. More...
 
tripoint global_part_pos3 (const vehicle_part &pt) const
 
tripoint_bub_ms bub_part_pos (int index) const
 
tripoint_bub_ms bub_part_pos (const vehicle_part &pt) const
 
std::map< itype_id, int > fuels_left () const
 All the fuels that are in all the tanks in the vehicle, nicely summed up. More...
 
std::list< item * > fuel_items_left ()
 All the individual fuel items that are in all the tanks in the vehicle. More...
 
int64_t fuel_left (const itype_id &ftype, const std::function< bool(const vehicle_part &)> &filter=return_true< const vehicle_part & >) const
 
int engine_fuel_left (const vehicle_part &vp) const
 
int fuel_capacity (const itype_id &ftype) const
 
int drain (const itype_id &ftype, int amount, const std::function< bool(vehicle_part &)> &filter=return_true< vehicle_part & >, bool apply_loss=true)
 
int drain (int index, int amount, bool apply_loss=true)
 
units::energy drain_energy (const itype_id &ftype, units::energy wanted_energy)
 Consumes enough fuel by energy content. More...
 
units::power basic_consumption (const itype_id &ftype) const
 
int consumption_per_hour (const itype_id &ftype, units::energy fuel_per_s) const
 
void consume_fuel (int load, bool idling)
 
std::map< itype_id, units::powerfuel_usage () const
 Maps used fuel to its basic (unscaled by load/strain) consumption. More...
 
units::power engine_fuel_usage (const vehicle_part &vp) const
 Fuel usage for specific engine. More...
 
std::vector< vehicle_part * > lights ()
 
void update_alternator_load ()
 
units::power total_engine_epower () const
 
units::power total_alternator_epower () const
 
units::power total_solar_epower () const
 
units::power total_wind_epower () const
 
units::power total_water_wheel_epower () const
 
units::power total_accessory_epower () const
 
units::power net_battery_charge_rate (bool include_reactors) const
 
units::power max_reactor_epower () const
 
units::power active_reactor_epower () const
 
void power_parts ()
 
std::pair< int, int > battery_power_level () const
 
std::pair< int, int > connected_battery_power_level () const
 
int64_t battery_left (bool apply_loss=true) const
 
int charge_battery (int amount, bool apply_loss=true)
 Charges batteries in connected vehicles/appliances. More...
 
int discharge_battery (int amount, bool apply_loss=true)
 Discharges batteries in connected vehicles/appliances. More...
 
void invalidate_mass ()
 Mark mass caches and pivot cache as dirty. More...
 
units::mass total_mass () const
 
const pointrotated_center_of_mass () const
 
const pointlocal_center_of_mass () const
 
const pointpivot_point () const
 
point pivot_displacement () const
 
units::power total_power (bool fueled=true, bool safe=false) const
 
int ground_acceleration (bool fueled=true, int at_vel_in_vmi=-1) const
 
int water_acceleration (bool fueled=true, int at_vel_in_vmi=-1) const
 
int rotor_acceleration (bool fueled=true, int at_vel_in_vmi=-1) const
 
int acceleration (bool fueled=true, int at_vel_in_vmi=-1) const
 
int current_acceleration (bool fueled=true) const
 
bool is_moving () const
 
bool can_use_rails () const
 
int max_ground_velocity (bool fueled=true) const
 
int max_water_velocity (bool fueled=true) const
 
int max_rotor_velocity (bool fueled=true) const
 
int max_velocity (bool fueled=true) const
 
int max_reverse_velocity (bool fueled=true) const
 
int safe_ground_velocity (bool fueled=true) const
 
int safe_rotor_velocity (bool fueled=true) const
 
int safe_water_velocity (bool fueled=true) const
 
int safe_velocity (bool fueled=true) const
 
void spew_field (double joules, int part, field_type_id type, int intensity=1) const
 
void noise_and_smoke (int load, time_duration time=1_turns)
 Generate noise or smoke from a vehicle with engines turned on load = how hard the engines are working, from 0.0 until 1.0 time = how many seconds to generated smoke for. More...
 
int wheel_area () const
 Calculates the sum of the area under the wheels of the vehicle. More...
 
float average_offroad_rating () const
 
double coeff_air_drag () const
 Physical coefficients used for vehicle calculations. More...
 
double coeff_rolling_drag () const
 coefficient of rolling resistance multiplied by velocity to get the variable part of rolling resistance drag in N multiplied by a constant to get the constant part of rolling resistance drag in N depends on wheel design, wheel number, and vehicle weight More...
 
double coeff_water_drag () const
 coefficient of water drag in kg/m multiplied by the square of speed to calculate water drag force in N proportional to cross sectional area of the vehicle, times the density of water, times a dimensional constant based on the vehicle's shape More...
 
double water_hull_height () const
 watertight hull height in meters measures distance from bottom of vehicle to the point where the vehicle will start taking on water More...
 
double water_draft () const
 water draft in meters - how much of the vehicle's body is under water must be less than the hull height or the boat will sink at some point, also add boats with deep draft running around More...
 
bool can_float () const
 can_float does the vehicle have freeboard or does it overflow with water? More...
 
bool is_in_water (bool deep_water=false) const
 is the vehicle mostly in water or mostly on fairly dry land? More...
 
bool is_watercraft () const
 should vehicle be handled using watercraft logic as determined by amount of water it is in (and whether it is amphibious) result being true does not guarantee it is viable boat – check can_float() More...
 
double lift_thrust_of_rotorcraft (bool fuelled, bool safe=false) const
 is the vehicle flying? is it a rotorcraft? More...
 
bool has_sufficient_rotorlift () const
 
int get_z_change () const
 
bool is_flying_in_air () const
 
void set_flying (bool new_flying_value)
 
bool is_rotorcraft () const
 
bool is_flyable () const
 
void set_flyable (bool val)
 
bool would_install_prevent_flyable (const vpart_info &vpinfo, const Character &pc) const
 
bool would_removal_prevent_flyable (const vehicle_part &vp, const Character &pc) const
 
bool would_repair_prevent_flyable (const vehicle_part &vp, const Character &pc) const
 
bool can_control_in_air (const Character &pc) const
 
bool can_control_on_land (const Character &pc) const
 
float k_traction (float wheel_traction_area) const
 Traction coefficient of the vehicle. More...
 
units::power static_drag (bool actual=true) const
 
float strain () const
 
bool sufficient_wheel_config () const
 
bool balanced_wheel_config () const
 
bool valid_wheel_config () const
 
float steering_effectiveness () const
 
float handling_difficulty () const
 Returns roughly driving skill level at which there is no chance of fumbling. More...
 
void idle (bool on_map)
 
void alarm ()
 
void slow_leak ()
 
void thrust (int thd, int z=0)
 
void smart_controller_handle_turn (const std::optional< float > &k_traction_cache=std::nullopt)
 if smart controller is enabled, turns on and off engines depending on load and battery level More...
 
bool has_available_electric_engine ()
 
void disable_smart_controller_if_needed ()
 
int slowdown (int velocity) const
 
void possibly_recover_from_skid ()
 
float forward_velocity () const
 
void cruise_thrust (int amount)
 
void turn (units::angle deg)
 
bool collision (std::vector< veh_collision > &colls, const tripoint &dp, bool just_detect, bool bash_floor=false)
 
veh_collision part_collision (int part, const tripoint &p, bool just_detect, bool bash_floor)
 
void handle_trap (const tripoint &p, vehicle_part &vp_wheel)
 
void activate_magical_follow ()
 
void activate_animal_follow ()
 
void selfdrive (const point &)
 vehicle is driving itself More...
 
bool check_heli_descend (Character &p) const
 can the helicopter descend/ascend here? More...
 
bool check_heli_ascend (Character &p) const
 
bool check_is_heli_landed ()
 
void pldrive (Character &driver, const point &p, int z=0)
 Player is driving the vehicle. More...
 
int prepare_tool (item &tool) const
 Flags item tool with PSEUDO, if it has MOD pocket then a pseudo_magazine_mod is installed and a pseudo_magazine is inserted into the magazine well pocket with however many ammo charges of the first ammo type required by the tool are available to this vehicle. More...
 
std::pair< const itype_id &, int > tool_ammo_available (const itype_id &tool_type) const
 if tool is not an itype with tool != nullptr this returns { itype::NULL_ID(), 0 } pair More...
 
std::map< item, int > prepare_tools (const vehicle_part &vp) const
 
void make_active (item_location &loc)
 Update an item's active status, for example when adding hot or perishable liquid to a container. More...
 
std::optional< vehicle_stack::iteratoradd_item (vehicle_part &vp, const item &itm)
 Try to add an item to part's cargo. More...
 
int add_charges (vehicle_part &vp, const item &itm)
 Add an item counted by charges to the part's cargo. More...
 
bool remove_item (vehicle_part &vp, item *it)
 
vehicle_stack::iterator remove_item (vehicle_part &vp, const vehicle_stack::const_iterator &it)
 
vehicle_stack get_items (const vehicle_part &vp) const
 
vehicle_stack get_items (vehicle_part &vp)
 
std::vector< item > & get_tools (vehicle_part &vp)
 
const std::vector< item > & get_tools (const vehicle_part &vp) const
 
void place_spawn_items ()
 
void place_zones (map &pmap) const
 
void gain_moves ()
 
bool decrement_summon_timer ()
 
void stop ()
 
void refresh_insides ()
 
void unboard_all () const
 
int damage (map &here, int p, int dmg, const damage_type_id &type=damage_type_id("bash"), bool aimed=true)
 
void damage_all (int dmg1, int dmg2, const damage_type_id &type, const point &impact)
 
void shift_parts (map &here, const point &delta)
 Shifts all parts of the vehicle by the given amounts, and then shifts the vehicle itself in the opposite direction. More...
 
bool shift_if_needed (map &here)
 Detect if the vehicle is currently missing a 0,0 part, and adjust if necessary. More...
 
void shed_loose_parts (trinary shed_cables=trinary::NONE, const tripoint_bub_ms *dst=nullptr)
 Drop parts with UNMOUNT_ON_MOVE onto the ground. More...
 
void unlink_cables (const point &mount, Character &remover, bool unlink_items=false, bool unlink_tow_cables=false, bool unlink_power_cords=false)
 Disconnect cables attached to the specified mount point. More...
 
vehicle_part_with_feature_range< std::string > get_avail_parts (std::string feature) const
 Yields a range of parts of this vehicle that each have the given feature and are available: not broken, removed, or part of a carried vehicle. More...
 
vehicle_part_with_feature_range< vpart_bitflagsget_avail_parts (vpart_bitflags f) const
 
vehicle_part_with_feature_range< std::string > get_parts_including_carried (std::string feature) const
 Yields a range of parts of this vehicle that each have the given feature and are not broken or removed. More...
 
vehicle_part_with_feature_range< vpart_bitflagsget_parts_including_carried (vpart_bitflags f) const
 
vehicle_part_with_feature_range< std::string > get_any_parts (std::string feature) const
 Yields a range of parts of this vehicle that each have the given feature and not removed. More...
 
vehicle_part_with_feature_range< vpart_bitflagsget_any_parts (vpart_bitflags f) const
 
vehicle_part_with_feature_range< std::string > get_enabled_parts (std::string feature) const
 Yields a range of parts of this vehicle that each have the given feature and are enabled and available: not broken, removed, or part of a carried vehicle. More...
 
vehicle_part_with_feature_range< vpart_bitflagsget_enabled_parts (vpart_bitflags f) const
 

Static Public Member Functions

static vehiclefind_vehicle (const tripoint_abs_ms &where)
 Find a possibly off-map vehicle. More...
 
static bool use_vehicle_tool (vehicle &veh, const tripoint &vp_pos, const itype_id &tool_type, bool no_invoke=false)
 

Public Attributes

std::set< pointcollision_check_points
 
units::power linked_item_epower_this_turn
 

Private Member Functions

bool has_structural_part (const point &dp) const
 
bool is_structural_part_removed () const
 Returns whether or not the vehicle has a structural part queued for removal,. More...
 
void open_or_close (int part_index, bool opening)
 Opens or closes an openable part at the specified index based on the @opening value passed. More...
 
void lock_or_unlock (int part_index, bool locking)
 Locks or unlocks a lockable door part at the specified index based on the @locking value passed. More...
 
bool is_connected (const vehicle_part &to, const vehicle_part &from, const vehicle_part &excluded) const
 Performs a breadth-first search from one part to another, to see if a path exists between the two without going through the excluded part. More...
 
int damage_direct (map &here, vehicle_part &vp, int dmg, const damage_type_id &type=damage_type_id("pure"))
 
int break_off (map &here, vehicle_part &vp, int dmg)
 
bool explode_fuel (vehicle_part &vp, const damage_type_id &type)
 
void smash_security_system ()
 
units::power part_vpower_w (const vehicle_part &vp, bool at_full_hp=false) const
 
units::power part_epower (const vehicle_part &vp) const
 
int power_to_energy_bat (units::power power, const time_duration &d) const
 
bool do_environmental_effects () const
 
void print_fuel_indicator (const catacurses::window &w, const point &p, const itype_id &fuel_type, bool verbose=false, bool desc=false)
 Prints a fuel gauge for a vehicle. More...
 
void print_fuel_indicator (const catacurses::window &w, const point &p, const itype_id &fuel_type, std::map< itype_id, units::energy > fuel_usages, bool verbose=false, bool desc=false)
 
time_duration engine_start_time (const vehicle_part &vp) const
 
double engine_cold_factor (const vehicle_part &vp) const
 
void refresh_pivot () const
 
void calc_mass_center (bool precalc) const
 
void leak_fuel (vehicle_part &pt) const
 empty the contents of a tank, battery or turret spilling liquids randomly on the ground More...
 
vehicleoperator= (const vehicle &)=default
 

Static Private Member Functions

template<typename Vehicle >
static std::map< Vehicle *, float > search_connected_vehicles (Vehicle *start)
 Returns a map of connected vehicle pointers to power loss factor: Keys are vehicles connected by POWER_TRANSFER parts, includes self Values are line loss, 0.01 corresponds to 1% charge loss to wire resistance May load the connected vehicles' submaps Templated to support const and non-const vehicle*. More...
 

Vehicle turrets

faction_id owner = faction_id::NULL_ID()
 
faction_id old_owner = faction_id::NULL_ID()
 
std::vector< int > alternators
 
std::vector< int > engines
 
std::vector< int > reactors
 
std::vector< int > solar_panels
 
std::vector< int > wind_turbines
 
std::vector< int > water_wheels
 
std::vector< int > sails
 
std::vector< int > funnels
 
std::vector< int > emitters
 
std::vector< int > loose_parts
 
std::vector< int > wheelcache
 
std::vector< int > rotors
 
std::vector< int > rail_wheelcache
 
std::vector< int > steering
 
std::vector< int > speciality
 
std::vector< int > floating
 
std::vector< int > batteries
 
std::vector< int > fuel_containers
 
std::vector< int > turret_locations
 
std::vector< int > mufflers
 
std::vector< int > planters
 
std::vector< int > accessories
 
std::vector< int > cable_ports
 
std::vector< int > fake_parts
 
std::vector< int > control_req_parts
 
std::string name
 
vproto_id type
 Type of the vehicle as it was spawned. More...
 
std::map< point, std::vector< int > > relative_parts
 
std::set< labellabels
 
std::set< std::string > tags
 
std::map< itype_id, units::energyfuel_remainder
 
std::map< itype_id, units::energyfuel_used_last_turn
 
std::unordered_multimap< point, zone_dataloot_zones
 
active_item_cache active_items
 
bool magic = false
 
std::optional< time_durationsummon_time_limit = std::nullopt
 
std::optional< smart_controller_cachesmart_controller_state = std::nullopt
 
std::optional< smart_controller_configsmart_controller_cfg = std::nullopt
 
bool has_enabled_smart_controller = false
 
tripoint sm_pos = tripoint_zero
 Submap coordinates of the currently loaded submap (see game::m) that contains this vehicle. More...
 
int alternator_load = 0
 
time_point last_update = calendar::before_time_starts
 
point pos = point_zero
 Position of the vehicle inside the submap that contains the vehicle. More...
 
int velocity = 0
 
int avg_velocity = 0
 vehicle continuous moving average velocity see https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average alpha is 0.5: avg_velocity = avg_velocity + 0.5(velocity - avg_velocity) = 0.5 avg_velocity + 0.5 velocity More...
 
int cruise_velocity = 0
 
int vertical_velocity = 0
 
int om_id = 0
 
units::angle turn_dir = 0_degrees
 
units::angle last_turn = 0_degrees
 
float of_turn = 0.0f
 
float of_turn_carry = 0.0f
 
units::power extra_drag = 0_W
 
std::optional< time_pointtheft_time
 
std::array< units::angle, 2 > pivot_rotation = { { 0_degrees, 0_degrees } }
 
bounding_box rail_wheel_bounding_box
 
point front_left
 
point front_right
 
towing_data tow_data
 
std::array< point, 2 > pivot_anchor
 
tileray face
 
tileray move
 
bool is_on_ramp = false
 
bool is_autodriving = false
 
bool is_following = false
 
bool is_patrolling = false
 
bool all_wheels_on_one_axis = false
 
bool engine_on = false
 
bool tracking_on = false
 
bool is_locked = false
 
bool is_alarm_on = false
 
bool camera_on = false
 
bool autopilot_on = false
 
bool precollision_on = true
 
bool skidding = false
 
bool check_environmental_effects = false
 
bool insides_dirty = true
 
bool is_falling = false
 
bool zones_dirty = true
 
unsigned char vehicle_noise = 0
 
double coefficient_air_resistance = 1
 
double coefficient_rolling_resistance = 1
 
double coefficient_water_resistance = 1
 
double draft_m = 1
 
double hull_height = 0.3
 
tripoint occupied_cache_pos = { -1, -1, -1 }
 
units::angle occupied_cache_direction = 0_degrees
 
std::set< tripointoccupied_points
 
std::vector< vehicle_partparts
 
std::map< point, vpart_edge_infoedges
 
safe_reference_anchor anchor
 
units::mass mass_cache
 
point pivot_cache
 
point mount_max
 
point mount_min
 
point mass_center_precalc
 
point mass_center_no_precalc
 
tripoint autodrive_local_target = tripoint_zero
 
std::shared_ptr< autodrive_controlleractive_autodrive_controller
 
bool no_refresh = false
 
bool pivot_dirty = true
 
bool mass_dirty = true
 
bool mass_center_precalc_dirty = true
 
bool mass_center_no_precalc_dirty = true
 
bool coeff_rolling_dirty = true
 
bool coeff_air_dirty = true
 
bool coeff_water_dirty = true
 
bool coeff_air_changed = true
 
bool in_deep_water = false
 
bool in_water = false
 
bool is_flying = false
 
bool flyable = true
 
int requested_z_change = 0
 
std::vector< vehicle_part * > find_all_ready_turrets (bool manual, bool automatic)
 
bool turrets_aim (std::vector< vehicle_part * > &turrets)
 
int turrets_aim_and_fire (std::vector< vehicle_part * > &turrets)
 
std::vector< std::reference_wrapper< const vehicle_part > > real_parts () const
 
vpart_edge_info get_edge_info (const point &mount) const
 
void remove_fake_parts (bool cleanup=true)
 
bool should_enable_fake (const tripoint &fake_precalc, const tripoint &parent_precalc, const tripoint &neighbor_precalc) const
 
std::vector< vehicle_part * > turrets ()
 Get all vehicle turrets (excluding any that are destroyed) More...
 
std::vector< vehicle_part * > turrets (const tripoint &target)
 Get all vehicle turrets loaded and ready to fire at target. More...
 
turret_data turret_query (vehicle_part &pt)
 Get firing data for a turret. More...
 
turret_data turret_query (const tripoint &pos)
 
void turrets_set_targeting ()
 Set targeting mode for specific turrets. More...
 
void turrets_set_mode ()
 Set firing mode for specific turrets. More...
 
void turrets_aim_and_fire_single ()
 Select a single ready turret, aim it using the aiming UI and fire. More...
 
bool turrets_aim_and_fire_all_manual (bool show_msg=false)
 
void turrets_override_automatic_aim ()
 Set target for automatic turrets using the aiming UI. More...
 
int automatic_fire_turret (vehicle_part &pt)
 
bool assign_seat (vehicle_part &pt, const npc &who)
 Try to assign a crew member (who must be a player ally) to a specific seat. More...
 
const std::set< tripoint > & get_points (bool force_refresh=false, bool no_fake=false) const
 
std::list< itemuse_charges (const vpart_position &vp, const itype_id &type, int &quantity, const std::function< bool(const item &)> &filter, bool in_tools=false)
 Consumes specified charges (or fewer) from the vehicle part. More...
 
void open (int part_index)
 Opens an openable part at the specified index. More...
 
void close (int part_index)
 Closes an openable part at the specified index. More...
 
void lock (int part_index)
 Locks a lockable, closed part at the specified index. More...
 
void unlock (int part_index)
 Unlocks a lockable, closed part at the specified index. More...
 
bool part_has_lock (int part_index) const
 
bool can_close (int part_index, Character &who)
 
bool is_foldable () const
 
time_duration folding_time () const
 
time_duration unfolding_time () const
 
item get_folded_item () const
 
bool restore_folded_parts (const item &it)
 
bool has_security_working () const
 
void unlock ()
 
void open_all_at (int p)
 Opens everything that can be opened on the same tile as p More...
 
void honk_horn () const
 
void reload_seeds (const tripoint &pos)
 
void beeper_sound () const
 
void play_music () const
 
void play_chimes () const
 
void operate_planter ()
 
void autopilot_patrol_check ()
 
void toggle_autopilot ()
 
void enable_patrol ()
 
void toggle_tracking ()
 
void operate_scoop ()
 
void operate_reaper ()
 
void crash_terrain_around ()
 
void transform_terrain ()
 
void control_engines ()
 
bool is_engine_type_on (const vehicle_part &vp, const itype_id &ft) const
 
bool is_engine_on (const vehicle_part &vp) const
 
bool is_engine_type (const vehicle_part &vp, const itype_id &ft) const
 
bool is_engine_type_combustion (const vehicle_part &vp) const
 
bool is_alternator_on (const vehicle_part &vp) const
 
bool start_engine (vehicle_part &vp, bool turn_on)
 
bool has_engine_type (const itype_id &ft, bool enabled) const
 
monsterget_harnessed_animal () const
 
bool has_engine_type_not (const itype_id &ft, bool enabled) const
 
std::optional< std::string > has_engine_conflict (const vpart_info &possible_conflict) const
 
bool is_perpetual_type (const vehicle_part &vp) const
 
void do_engine_damage (vehicle_part &vp, int strain)
 
void control_doors ()
 
rl_vec2d velo_vec () const
 
rl_vec2d face_vec () const
 
rl_vec2d move_vec () const
 
rl_vec2d dir_vec () const
 
void on_move ()
 
vehicleact_on_map ()
 
void check_falling_or_floating ()
 
void precalculate_vehicle_turning (units::angle new_turn_dir, bool check_rail_direction, ter_furn_flag ter_flag_to_check, int &wheels_on_rail, int &turning_wheels_that_are_one_axis_counter) const
 Precalculate vehicle turn. More...
 
bool allow_auto_turn_on_rails (units::angle &corrected_turn_dir) const
 
bool allow_manual_turn_on_rails (units::angle &corrected_turn_dir) const
 
bool is_wheel_state_correct_to_turn_on_rails (int wheels_on_rail, int wheel_count, int turning_wheels_that_are_one_axis) const
 
void set_submap_moved (const tripoint &p)
 Update the submap coordinates and update the tracker info in the overmap (if enabled). More...
 
void use_autoclave (int p)
 
void use_washing_machine (int p)
 
void use_dishwasher (int p)
 
void use_monster_capture (int part, const tripoint &pos)
 
void use_harness (int part, const tripoint &pos)
 
void build_electronics_menu (veh_menu &menu)
 
void build_bike_rack_menu (veh_menu &menu, int part)
 
void build_interact_menu (veh_menu &menu, const tripoint &p, bool with_pickup)
 
void interact_with (const tripoint &p, bool with_pickup=false)
 
std::string disp_name () const
 
int lift_strength () const
 Required strength to be able to successfully lift the vehicle unaided by equipment. More...
 
bool refresh_zones ()
 
bounding_box get_bounding_box (bool use_precalc=true, bool no_fake=false)
 
void update_time (const time_point &update_to)
 
int part_count () const
 
int part_count_real () const
 
int part_count_real_cached () const
 
vehicle_partpart (int part_num)
 
const vehicle_partpart (int part_num) const
 
int get_non_fake_part (int part_num) const
 
void update_active_fakes ()
 
item part_to_item (const vehicle_part &vp) const
 Generate the corresponding item from this vehicle part. More...
 
item removed_part (const vehicle_part &vp) const
 If the vehicle part has an item it is removed as, transform the item to the item it is removed_as. More...
 
std::set< int > advance_precalc_mounts (const point &new_pos, const tripoint &src, const tripoint &dp, int ramp_offset, bool adjust_pos, std::set< int > parts_to_move)
 
bool level_vehicle ()
 
void add_tag (const std::string &tag)
 
bool has_tag (const std::string &tag) const
 
std::pair< int, double > get_exhaust_part () const
 
tripoint exhaust_dest (int part) const
 
std::vector< std::tuple< point, int, std::string > > get_debug_overlay_data () const
 

Detailed Description

A vehicle as a whole with all its components.

This object can occupy multiple tiles, the objects actually visible on the map are of type vehicle_part.

Facts you need to know about implementation:

Definition at line 801 of file vehicle.h.

Constructor & Destructor Documentation

◆ vehicle() [1/2]

vehicle::vehicle ( const vproto_id proto_id)
explicit

Definition at line 214 of file vehicle.cpp.

215 {
216  face.init( 0_degrees );
217  move.init( 0_degrees );
218 
219  if( proto_id.is_empty() ) {
220  refresh(); // we're not using any blueprint, just return an empty initialized vehicle
221  } else if( !proto_id.is_valid() ) {
222  debugmsg( "trying to construct vehicle from invalid prototype '%s'", proto_id.str() );
223  } else {
224  type = proto_id;
225  const vehicle_prototype &proto = *type;
226  // Copy the already made vehicle. The blueprint is created when the json data is loaded
227  // and is guaranteed to be valid (has valid parts etc.).
228  *this = *proto.blueprint;
229  // The game language may have changed after the blueprint was created,
230  // so translated the prototype name again.
231  name = proto.name.translated();
232  refresh();
233  }
234 }
bool is_valid() const
Returns whether this id is valid, that means whether it refers to an existing object.
Definition: achievement.cpp:78
bool is_empty() const
Returns whether this id is empty.
Definition: string_id.h:303
const std::string & str() const
Returns the identifier as plain std::string.
Definition: string_id.h:260
void init(const point &ad)
Definition: tileray.cpp:26
std::string translated(int num=1) const
Returns raw string if no translation is needed, otherwise returns the translated string.
vproto_id type
Type of the vehicle as it was spawned.
Definition: vehicle.h:2207
std::string name
Definition: vehicle.h:2201
tileray move
Definition: vehicle.h:2314
tileray face
Definition: vehicle.h:2312
void refresh(bool remove_fakes=true)
Refreshes all caches and refinds all parts.
Definition: vehicle.cpp:6179
#define debugmsg(...)
Debug message of level D_ERROR and class D_MAIN, also includes the source file name and line,...
Definition: debug.h:69
Prototype of a vehicle.
Definition: veh_type.h:483
translation name
Definition: veh_type.h:504
shared_ptr_fast< vehicle > blueprint
Definition: veh_type.h:509

References vehicle_prototype::blueprint, debugmsg, face, tileray::init(), string_id< T >::is_empty(), string_id< T >::is_valid(), move, vehicle_prototype::name, name, refresh(), string_id< T >::str(), translation::translated(), and type.

Referenced by map::add_splatter(), doors::can_lock_door(), doors::can_unlock_door(), doors::close_door(), game::control_vehicle(), map::deregister_vehicle_zone(), unload_loot_activity_actor::do_turn(), optional_vpart_position::extended_description(), advanced_inv_area::init(), doors::lock_door(), map::mop_spills(), monster::move(), open(), pldrive(), advanced_inv_area::set_container_position(), set_item_map_or_vehicle(), map::terrain_moppable(), and doors::unlock_door().

◆ vehicle() [2/2]

vehicle::vehicle ( const vehicle )
delete

◆ ~vehicle()

vehicle::~vehicle ( )
default

Member Function Documentation

◆ acceleration()

int vehicle::acceleration ( bool  fueled = true,
int  at_vel_in_vmi = -1 
) const

Definition at line 3839 of file vehicle.cpp.

3840 {
3841  if( is_watercraft() ) {
3842  return water_acceleration( fueled, at_vel_in_vmi );
3843  } else if( is_rotorcraft() && is_flying ) {
3844  return rotor_acceleration( fueled, at_vel_in_vmi );
3845  }
3846  return ground_acceleration( fueled, at_vel_in_vmi );
3847 }
bool is_flying
Definition: vehicle.h:2340
bool is_watercraft() const
should vehicle be handled using watercraft logic as determined by amount of water it is in (and wheth...
Definition: vehicle.cpp:4457
int rotor_acceleration(bool fueled=true, int at_vel_in_vmi=-1) const
Definition: vehicle.cpp:3773
bool is_rotorcraft() const
Definition: vehicle.cpp:4391
int ground_acceleration(bool fueled=true, int at_vel_in_vmi=-1) const
Definition: vehicle.cpp:3752
int water_acceleration(bool fueled=true, int at_vel_in_vmi=-1) const
Definition: vehicle.cpp:3783

References ground_acceleration(), is_flying, is_rotorcraft(), is_watercraft(), rotor_acceleration(), and water_acceleration().

Referenced by current_acceleration().

◆ act_on_map()

vehicle * vehicle::act_on_map ( )

Definition at line 1813 of file vehicle_move.cpp.

1814 {
1815  const tripoint pt = global_pos3();
1816  map &here = get_map();
1817  if( !here.inbounds( pt ) ) {
1818  dbg( D_INFO ) << "stopping out-of-map vehicle. (x,y,z)=(" << pt.x << "," << pt.y << "," << pt.z <<
1819  ")";
1820  stop();
1821  of_turn = 0;
1822  is_falling = false;
1823  return this;
1824  }
1825  if( decrement_summon_timer() ) {
1826  return nullptr;
1827  }
1828  Character &player_character = get_player_character();
1829  const bool pl_ctrl = player_in_control( player_character );
1830  // TODO: Remove this hack, have vehicle sink a z-level
1831  if( in_deep_water && !can_float() ) {
1832  add_msg( m_bad, _( "Your %s sank." ), name );
1833  if( pl_ctrl ) {
1834  unboard_all();
1835  }
1836  if( g->remoteveh() == this ) {
1837  g->setremoteveh( nullptr );
1838  }
1839 
1840  here.on_vehicle_moved( sm_pos.z );
1841  // Destroy vehicle (sank to nowhere)
1842  here.destroy_vehicle( this );
1843  return nullptr;
1844  }
1845 
1846  // It needs to fall when it has no support OR was falling before
1847  // so that vertical collisions happen.
1848  const bool should_fall = is_falling || vertical_velocity != 0;
1849 
1850  // TODO: Saner diagonal movement, so that you can jump off cliffs properly
1851  // The ratio of vertical to horizontal movement should be vertical_velocity/velocity
1852  // for as long as of_turn doesn't run out.
1853  if( should_fall ) {
1854  // 9.8 m/s^2
1855  const float g = 9.8f;
1856  // Convert from 100*mph to m/s
1857  const float old_vel = vmiph_to_mps( vertical_velocity );
1858  // Formula is v_2 = sqrt( 2*d*g + v_1^2 )
1859  // Note: That drops the sign
1860  const float new_vel = -std::sqrt( 2 * tile_height * g + old_vel * old_vel );
1861  vertical_velocity = mps_to_vmiph( new_vel );
1862  is_falling = true;
1863  } else {
1864  // Not actually falling, was just marked for fall test
1865  is_falling = false;
1866  }
1867 
1868  // Low enough for bicycles to go in reverse.
1869  // If the movement is due to a change in z-level, i.e a helicopter then the lateral movement will often be zero.
1870  if( !should_fall && std::abs( velocity ) < 20 && requested_z_change == 0 ) {
1871  stop();
1872  of_turn -= .321f;
1873  return this;
1874  }
1875 
1876  const float wheel_traction_area = here.vehicle_wheel_traction( *this );
1877  const float traction = k_traction( wheel_traction_area );
1878  if( traction < 0.001f ) {
1879  of_turn = 0;
1880  if( !should_fall ) {
1881  stop();
1882  if( floating.empty() ) {
1883  add_msg( m_info, _( "Your %s can't move on this terrain." ), name );
1884  } else {
1885  add_msg( m_info, _( "Your %s is beached." ), name );
1886  }
1887  return this;
1888  }
1889  }
1890  const float turn_cost = vehicles::vmiph_per_tile / std::max<float>( 0.0001f, std::abs( velocity ) );
1891 
1892  // Can't afford it this turn?
1893  // Low speed shouldn't prevent vehicle from falling, though
1894  bool falling_only = false;
1895  if( turn_cost >= of_turn && ( ( !is_flying && requested_z_change == 0 ) || !is_rotorcraft() ) ) {
1896  if( !should_fall ) {
1898  of_turn = 0;
1899  return this;
1900  }
1901  falling_only = true;
1902  }
1903 
1904  // Decrease of_turn if falling+moving, but not when it's lower than move cost
1905  if( !falling_only ) {
1906  of_turn -= turn_cost;
1907  }
1908 
1909  bool can_use_rails = this->can_use_rails();
1910  if( one_in( 10 ) ) {
1911  bool controlled = false;
1912  // It can even be a NPC, but must be at the controls
1913  for( int boarded : boarded_parts() ) {
1914  if( part_with_feature( boarded, VPFLAG_CONTROLS, true ) >= 0 ) {
1915  controlled = true;
1916  Character *passenger = get_passenger( boarded );
1917  if( passenger != nullptr ) {
1918  passenger->practice( skill_driving, 1 );
1919  }
1920  }
1921  }
1922 
1923  // Eventually send it skidding if no control
1924  // But not if it's remotely controlled, is in water or can use rails
1925  if( !controlled && !pl_ctrl && !( is_watercraft() && can_float() ) && !can_use_rails &&
1926  !is_flying && requested_z_change == 0 ) {
1927  skidding = true;
1928  }
1929  }
1930 
1931  if( skidding && one_in( 4 ) ) {
1932  // Might turn uncontrollably while skidding
1933  turn( vehicles::steer_increment * ( one_in( 2 ) ? -1 : 1 ) );
1934  }
1935 
1936  if( should_fall ) {
1937  // TODO: Insert a (hard) driving test to stop this from happening
1938  skidding = true;
1939  }
1940 
1941  bool allow_turn_on_rail = false;
1942  if( can_use_rails && !falling_only ) {
1943  units::angle corrected_turn_dir;
1944  allow_turn_on_rail = allow_manual_turn_on_rails( corrected_turn_dir );
1945  if( !allow_turn_on_rail ) {
1946  allow_turn_on_rail = allow_auto_turn_on_rails( corrected_turn_dir );
1947  }
1948  if( allow_turn_on_rail ) {
1949  turn_dir = corrected_turn_dir;
1950  }
1951  }
1952 
1953  // The direction we're moving
1954  tileray mdir;
1955  if( skidding || should_fall ) {
1956  // If skidding, it's the move vector
1957  // Same for falling - no air control
1958  mdir = move;
1959  } else if( turn_dir != face.dir() && ( !can_use_rails || allow_turn_on_rail ) ) {
1960  // Driver turned vehicle, get turn_dir
1961  mdir.init( turn_dir );
1962  } else {
1963  // Not turning, keep face.dir
1964  mdir = face;
1965  }
1966 
1967  tripoint dp;
1968  if( std::abs( velocity ) >= 20 && !falling_only ) {
1969  mdir.advance( velocity < 0 ? -1 : 1 );
1970  dp.x = mdir.dx();
1971  dp.y = mdir.dy();
1972  }
1973 
1974  if( should_fall ) {
1975  dp.z = -1;
1976  is_flying = false;
1977  } else {
1978  dp.z = requested_z_change;
1979  requested_z_change = 0;
1980  if( dp.z > 0 && is_rotorcraft() ) {
1981  is_flying = true;
1982  }
1983  }
1984 
1985  return here.move_vehicle( *this, dp, mdir );
1986 }
Character & get_player_character()
Definition: game.cpp:13807
bool practice(const skill_id &id, int amount, int cap=99, bool suppress_warning=false)
This handles giving xp for a skill.
Definition: character.cpp:2683
Manage and cache data about a part of the map.
Definition: map.h:346
float vehicle_wheel_traction(const vehicle &veh, bool ignore_movement_modifiers=false) const
bool inbounds(const tripoint &p) const
Definition: map.cpp:9057
void on_vehicle_moved(int smz)
Callback invoked when a vehicle has moved.
Definition: map.cpp:631
void destroy_vehicle(vehicle *veh)
Definition: map.cpp:626
vehicle * move_vehicle(vehicle &veh, const tripoint &dp, const tileray &facing)
Definition: map.cpp:752
int dy() const
Definition: tileray.cpp:68
void advance(int num=1)
Definition: tileray.cpp:105
units::angle dir() const
Definition: tileray.cpp:73
int dx() const
Definition: tileray.cpp:63
void turn(units::angle deg)
bool skidding
Definition: vehicle.h:2363
bool player_in_control(const Character &p) const
Definition: vehicle.cpp:253
tripoint sm_pos
Submap coordinates of the currently loaded submap (see game::m) that contains this vehicle.
Definition: vehicle.h:2261
tripoint global_pos3() const
Definition: vehicle.cpp:3431
float of_turn_carry
Definition: vehicle.h:2297
bool allow_auto_turn_on_rails(units::angle &corrected_turn_dir) const
int vertical_velocity
Definition: vehicle.h:2286
int velocity
Definition: vehicle.h:2276
void stop()
bool can_use_rails() const
Definition: vehicle.cpp:3733
float k_traction(float wheel_traction_area) const
Traction coefficient of the vehicle.
Definition: vehicle.cpp:4560
Character * get_passenger(int you) const
Definition: vehicle.cpp:3403
bool in_deep_water
Definition: vehicle.h:2335
std::vector< int > boarded_parts() const
Definition: vehicle.cpp:3362
bool decrement_summon_timer()
Definition: vehicle.cpp:6111
bool can_float() const
can_float does the vehicle have freeboard or does it overflow with water?
Definition: vehicle.cpp:4349
int part_with_feature(const point &pt, const std::string &f, bool unbroken) const
Returns index of part at mount point pt which has given f flag.
Definition: vehicle.cpp:2785
std::vector< int > floating
Definition: vehicle.h:2189
bool is_falling
Definition: vehicle.h:2369
int requested_z_change
Definition: vehicle.h:2342
void unboard_all() const
Definition: vehicle.cpp:7134
units::angle turn_dir
Definition: vehicle.h:2291
float of_turn
Definition: vehicle.h:2295
bool allow_manual_turn_on_rails(units::angle &corrected_turn_dir) const
@ D_INFO
Definition: debug.h:140
@ m_info
Definition: enums.h:352
@ m_bad
Definition: enums.h:348
std::unique_ptr< game > g
Definition: game.cpp:382
map & get_map()
Definition: game.cpp:13822
double abs(std::vector< double > const &params)
double sqrt(std::vector< double > const &params)
void add_msg(std::string msg)
Definition: messages.cpp:997
constexpr float vmiph_per_tile
Definition: vehicle.h:81
constexpr units::angle steer_increment
Definition: vehicle.h:83
bool one_in(int chance)
Definition: rng.cpp:108
int y
Definition: point.h:133
int z
Definition: point.h:134
int x
Definition: point.h:132
#define _(STRING)
Definition: translations.h:89
@ VPFLAG_CONTROLS
Definition: veh_type.h:69
int mps_to_vmiph(double mps)
#define dbg(x)
double vmiph_to_mps(int vmiph)
static const float tile_height
static const skill_id skill_driving("driving")

References _, abs(), add_msg(), tileray::advance(), allow_auto_turn_on_rails(), allow_manual_turn_on_rails(), boarded_parts(), can_float(), can_use_rails(), D_INFO, dbg, decrement_summon_timer(), map::destroy_vehicle(), tileray::dir(), tileray::dx(), tileray::dy(), face, floating, g, get_map(), get_passenger(), get_player_character(), global_pos3(), in_deep_water, map::inbounds(), tileray::init(), is_falling, is_flying, is_rotorcraft(), is_watercraft(), k_traction(), m_bad, m_info, move, map::move_vehicle(), mps_to_vmiph(), name, of_turn, of_turn_carry, map::on_vehicle_moved(), one_in(), part_with_feature(), player_in_control(), Character::practice(), requested_z_change, skidding, skill_driving, sm_pos, sqrt(), vehicles::steer_increment, stop(), tile_height, turn(), turn_dir, unboard_all(), map::vehicle_wheel_traction(), velocity, vertical_velocity, vehicles::vmiph_per_tile, vmiph_to_mps(), VPFLAG_CONTROLS, tripoint::x, tripoint::y, and tripoint::z.

Referenced by map::vehproceed().

◆ activate_animal_follow()

void vehicle::activate_animal_follow ( )

Definition at line 596 of file vehicle.cpp.

597 {
598  for( size_t e = 0; e < parts.size(); e++ ) {
599  vehicle_part &vp = parts[ e ];
600  if( vp.info().fuel_type == fuel_type_animal ) {
601  monster *mon = get_monster( e );
602  if( mon && mon->has_effect( effect_harnessed ) ) {
603  vp.enabled = true;
604  is_following = true;
605  engine_on = true;
606  }
607  } else {
608  vp.enabled = true;
609  }
610  }
611  refresh();
612 }
bool has_effect(const efftype_id &eff_id, const bodypart_id &bp) const
Check if creature has the matching effect.
Definition: creature.cpp:1770
bool engine_on
Definition: vehicle.h:2352
bool is_following
Definition: vehicle.h:2348
monster * get_monster(int p) const
Definition: vehicle.cpp:3412
std::vector< vehicle_part > parts
Definition: vehicle.h:2121
itype_id fuel_type
Fuel type of engine or tank.
Definition: veh_type.h:382
Structure, describing vehicle part (i.e., wheel, seat)
Definition: vehicle.h:254
const vpart_info & info() const
Get part definition common to all parts of this type.
bool enabled
Definition: vehicle.h:507
static const efftype_id effect_harnessed("harnessed")
static const itype_id fuel_type_animal("animal")

References effect_harnessed, vehicle_part::enabled, engine_on, vpart_info::fuel_type, fuel_type_animal, get_monster(), Creature::has_effect(), vehicle_part::info(), is_following, parts, and refresh().

Referenced by assign_veh_to_follow().

◆ activate_magical_follow()

void vehicle::activate_magical_follow ( )

Definition at line 582 of file vehicle.cpp.

583 {
584  for( vehicle_part &vp : parts ) {
585  if( vp.info().fuel_type == fuel_type_mana ) {
586  vp.enabled = true;
587  is_following = true;
588  engine_on = true;
589  } else {
590  vp.enabled = true;
591  }
592  }
593  refresh();
594 }
static const itype_id fuel_type_mana("mana")

References engine_on, fuel_type_mana, is_following, parts, and refresh().

Referenced by tell_magic_veh_to_follow().

◆ active_reactor_epower()

units::power vehicle::active_reactor_epower ( ) const

Definition at line 5164 of file vehicle.cpp.

5165 {
5166  units::power reactors_flow = 0_W;
5167  for( const int p : reactors ) {
5168  const vehicle_part &vp = parts[p];
5169  if( vp.enabled && vp.is_available() &&
5170  ( vp.info().has_flag( STATIC( std::string( "PERPETUAL" ) ) ) || vp.ammo_remaining() ) ) {
5171  reactors_flow += part_epower( vp );
5172  }
5173  }
5174 
5175  if( reactors_flow <= 0_W ) {
5176  return 0_W; // reactors don't output any power
5177  }
5178 
5179  // Reactors are providing power, but not all of it will really be used.
5180  // Only count as much power as will be drawn from the reactor to fill the batteries.
5181  const auto [bat_remaining, bat_capacity] = connected_battery_power_level();
5182  // max power flow into batteries for next turn
5183  const units::power max_battery_flow = units::from_kilowatt( static_cast<std::int64_t>
5184  ( bat_capacity - bat_remaining ) );
5185  // power flow by all parts except reactors
5186  const units::power non_reactor_flow = net_battery_charge_rate( false );
5187 
5188  if( non_reactor_flow >= max_battery_flow ) {
5189  return 0_W; // other parts will fully charge battery without a reactor involved
5190  }
5191  // return how much power the reactor will contribute after other parts
5192  return std::min( reactors_flow, max_battery_flow - non_reactor_flow );
5193 }
std::vector< int > reactors
Definition: vehicle.h:2174
std::pair< int, int > connected_battery_power_level() const
Definition: vehicle.cpp:5026
units::power part_epower(const vehicle_part &vp) const
Definition: vehicle.cpp:1137
units::power net_battery_charge_rate(bool include_reactors) const
Definition: vehicle.cpp:5157
bool has_flag(const std::string &flag) const
Definition: veh_type.h:256
#define STATIC(expr)
The purpose of this macro is to provide a concise syntax for creation of inline literals (std::string...
Definition: make_static.h:31
double min(std::vector< double > const &params)
constexpr quantity< value_type, power_in_milliwatt_tag > from_kilowatt(const value_type v)
Definition: units.h:609
bool is_available(bool carried=true) const
parts are available if they aren't unavailable
int ammo_remaining() const
Amount of fuel, charges or ammunition currently contained by a part.

References vehicle_part::ammo_remaining(), connected_battery_power_level(), vehicle_part::enabled, units::from_kilowatt(), vpart_info::has_flag(), vehicle_part::info(), vehicle_part::is_available(), min(), net_battery_charge_rate(), part_epower(), parts, reactors, and STATIC.

Referenced by veh_app_interact::draw_info(), and net_battery_charge_rate().

◆ add_charges()

int vehicle::add_charges ( vehicle_part vp,
const item itm 
)

Add an item counted by charges to the part's cargo.

Returns
The number of charges added.

Definition at line 5837 of file vehicle.cpp.

5838 {
5839  if( !itm.count_by_charges() ) {
5840  debugmsg( "Add charges was called for an item not counted by charges!" );
5841  return 0;
5842  }
5843  const int ret = get_items( vp ).amount_can_fit( itm );
5844  if( ret == 0 ) {
5845  return 0;
5846  }
5847 
5848  item itm_copy = itm;
5849  itm_copy.charges = ret;
5850  return add_item( vp, itm_copy ) ? ret : 0;
5851 }
int amount_can_fit(const item &it) const
Returns how many of the specified item (or how many charges if it's counted by charges) could be adde...
Definition: item_stack.cpp:111
Definition: item.h:196
bool count_by_charges() const
Return true if this item's type is counted by charges (true for stackable, ammo, or comestible)
Definition: item.cpp:8618
int charges
Definition: item.h:3133
std::optional< vehicle_stack::iterator > add_item(vehicle_part &vp, const item &itm)
Try to add an item to part's cargo.
Definition: vehicle.cpp:5853
vehicle_stack get_items(const vehicle_part &vp) const
Definition: vehicle.cpp:5922

References add_item(), item_stack::amount_can_fit(), item::charges, item::count_by_charges(), debugmsg, get_items(), and cata::hash64_detail::ret.

Referenced by put_into_vehicle().

◆ add_item()

std::optional< vehicle_stack::iterator > vehicle::add_item ( vehicle_part vp,
const item itm 
)

Try to add an item to part's cargo.

Returns
iterator to added item or std::nullopt if it can't be put here (not a cargo part, adding this would violate the volume limit or item count limit, not all charges can fit, etc.)

Definition at line 5853 of file vehicle.cpp.

5854 {
5855  // const int max_weight = ?! // TODO: weight limit, calculation per vpart & vehicle stats, not a hard user limit.
5856  // add creaking sounds and damage to overloaded vpart, outright break it past a certain point, or when hitting bumps etc
5857  if( vp.is_broken() ) {
5858  return std::nullopt;
5859  }
5860 
5861  if( vp.base.is_gun() ) {
5862  if( !itm.is_ammo() || !vp.base.ammo_types().count( itm.ammo_type() ) ) {
5863  return std::nullopt;
5864  }
5865  }
5866  bool charge = itm.count_by_charges();
5867  vehicle_stack istack = get_items( vp );
5868  const int to_move = istack.amount_can_fit( itm );
5869  if( to_move == 0 || ( charge && to_move < itm.charges ) ) {
5870  return std::nullopt; // @add_charges should be used in the latter case
5871  }
5872  if( charge ) {
5873  item *here = istack.stacks_with( itm );
5874  if( here ) {
5875  invalidate_mass();
5876  if( !here->merge_charges( itm ) ) {
5877  return std::nullopt;
5878  } else {
5879  return std::optional<vehicle_stack::iterator>( istack.get_iterator_from_pointer( here ) );
5880  }
5881  }
5882  }
5883 
5884  item itm_copy = itm;
5885 
5886  if( itm_copy.is_bucket_nonempty() ) {
5887  // this is a vehicle, so there is only one pocket.
5888  // so if it will spill, spill all of it
5889  itm_copy.spill_contents( global_part_pos3( vp ) );
5890  }
5891 
5892  const vehicle_stack::iterator new_pos = vp.items.insert( itm_copy );
5893  active_items.add( *new_pos, vp.mount );
5894 
5895  invalidate_mass();
5896  return std::optional<vehicle_stack::iterator>( new_pos );
5897 }
bool add(item &it, point location, item *parent=nullptr, std::vector< item_pocket const * > const &pocket_chain={})
Adds the reference to the cache.
iterator insert(const element_type &element)
Inserts the element supplied to the colony, using the object's copy-constructor.
Definition: colony.h:952
iterator get_iterator_from_pointer(item *it)
Definition: item_stack.cpp:72
item * stacks_with(const item &it)
Return the item (or nullptr) that stacks with the argument.
Definition: item_stack.cpp:125
bool is_gun() const
Can this item be used to perform a ranged attack?
Definition: item.cpp:9297
bool merge_charges(const item &rhs)
Merge charges of the other item into this item.
Definition: item.cpp:1755
bool spill_contents(Character &c)
Unloads the item's contents.
Definition: item.cpp:10206
ammotype ammo_type() const
Ammo type of an ammo item.
Definition: item.cpp:11073
bool is_ammo() const
Definition: item.cpp:9470
std::set< ammotype > ammo_types(bool conversion=true) const
Ammo types (ammunition_type) the item magazine pocket can contain.
Definition: item.cpp:11056
bool is_bucket_nonempty() const
Definition: item.cpp:9746
void invalidate_mass()
Mark mass caches and pivot cache as dirty.
Definition: vehicle.cpp:7986
active_item_cache active_items
Definition: vehicle.h:2217
tripoint global_part_pos3(const int &index) const
Get the coordinates of the studied part of the vehicle.
Definition: vehicle.cpp:3442
item base
Definition: vehicle.h:541
point mount
mount point: x is on the forward/backward axis, y is on the left/right axis
Definition: vehicle.h:447
cata::colony< item > items
Definition: vehicle.h:545
bool is_broken() const
parts are considered broken at zero health

References active_items, active_item_cache::add(), item::ammo_type(), item::ammo_types(), item_stack::amount_can_fit(), vehicle_part::base, item::charges, item::count_by_charges(), get_items(), item_stack::get_iterator_from_pointer(), global_part_pos3(), cata::colony< element_type, element_allocator_type, element_skipfield_type >::insert(), invalidate_mass(), item::is_ammo(), vehicle_part::is_broken(), item::is_bucket_nonempty(), item::is_gun(), vehicle_part::items, item::merge_charges(), vehicle_part::mount, item::spill_contents(), and item_stack::stacks_with().

Referenced by add_charges(), unload_loot_activity_actor::do_turn(), vehicle_stack::insert(), move_item(), operate_reaper(), operate_scoop(), place_spawn_items(), put_into_vehicle(), and set_item_map_or_vehicle().

◆ add_tag()

void vehicle::add_tag ( const std::string &  tag)

Definition at line 8317 of file vehicle.cpp.

8318 {
8319  tags.insert( tag );
8320 }
std::set< std::string > tags
Definition: vehicle.h:2211

References tags.

Referenced by merge_appliance_into_grid(), place_appliance(), and split_vehicles().

◆ advance_precalc_mounts()

std::set< int > vehicle::advance_precalc_mounts ( const point new_pos,
const tripoint src,
const tripoint dp,
int  ramp_offset,
bool  adjust_pos,
std::set< int >  parts_to_move 
)

Definition at line 8153 of file vehicle.cpp.

8156 {
8157  map &here = get_map();
8158  std::set<int> smzs;
8159  // when a vehicle part enters the low end of a down ramp, or the high end of an up ramp,
8160  // it immediately translates down or up a z-level, respectively, ending up on the low
8161  // end of an up ramp or high end of a down ramp, respectively. The two ends are set
8162  // past each other, like so:
8163  // (side view) z+1 Rdh RDl
8164  // z+0 RUh Rul
8165  // A vehicle moving left to right on z+1 drives down to z+0 by entering the ramp down low end.
8166  // A vehicle moving right to left on z+0 drives up to z+1 by entering the ramp up high end.
8167  // A vehicle moving left to right on z+0 should ideally collide into a wall before entering
8168  // the ramp up high end, but even if it does, it briefly transitions to z+1 before returning
8169  // to z0 by entering the ramp down low end.
8170  // A vehicle moving right to left on z+1 drives down to z+0 by entering the ramp down low end,
8171  // then immediately returns to z+1 by entering the ramp up high end.
8172  // When a vehicle's pivot point transitions a z-level via a ramp, all other pre-calc points
8173  // make the opposite transition, so that points that were above an ascending pivot point are
8174  // now level with it, and parts that were level with an ascending pivot point are now below
8175  // it.
8176  // parts that enter the translation portion of a ramp on the same displacement as the
8177  // pivot point stay at the same relative z to the pivot point, as the ramp_offset adjustments
8178  // cancel out.
8179  // if a vehicle manages move partially up or down a ramp and then veers off course, it
8180  // can get split across the z-levels and continue moving, enough though large parts of the
8181  // vehicle are unsupported. In that case, move the unsupported parts down until they are
8182  // supported.
8183  int index = -1;
8184  for( vehicle_part &prt : parts ) {
8185  index += 1;
8186  if( prt.is_real_or_active_fake() ) {
8187  here.clear_vehicle_point_from_cache( this, src + prt.precalc[0] );
8188  }
8189  // no parts means this is a normal horizontal or vertical move
8190  if( parts_to_move.empty() ) {
8191  prt.precalc[0] = prt.precalc[1];
8192  // partial part movement means we're zero-ing out after missing a ramp
8193  } else if( adjust_pos && parts_to_move.find( index ) == parts_to_move.end() ) {
8194  prt.precalc[0].z -= dp.z;
8195  } else if( !adjust_pos && parts_to_move.find( index ) != parts_to_move.end() ) {
8196  prt.precalc[0].z += dp.z;
8197  }
8198  if( here.has_flag( ter_furn_flag::TFLAG_RAMP_UP, src + dp + prt.precalc[0] ) ) {
8199  prt.precalc[0].z += 1;
8200  } else if( here.has_flag( ter_furn_flag::TFLAG_RAMP_DOWN, src + dp + prt.precalc[0] ) ) {
8201  prt.precalc[0].z -= 1;
8202  }
8203  prt.precalc[0].z -= ramp_offset;
8204  prt.precalc[1].z = prt.precalc[0].z;
8205  smzs.insert( prt.precalc[0].z );
8206  }
8207  if( adjust_pos ) {
8208  if( parts_to_move.empty() ) {
8209  pivot_anchor[0] = pivot_anchor[1];
8211  }
8212  pos = new_pos;
8213  }
8214  occupied_cache_pos = { -1, -1, -1 };
8215  return smzs;
8216 }
bool has_flag(const std::string &flag, const tripoint &p) const
Definition: map.cpp:3077
void clear_vehicle_point_from_cache(vehicle *veh, const tripoint &pt)
Definition: map.cpp:480
point pos
Position of the vehicle inside the submap that contains the vehicle.
Definition: vehicle.h:2274
std::array< units::angle, 2 > pivot_rotation
Definition: vehicle.h:2303
tripoint occupied_cache_pos
Definition: vehicle.h:2114
std::array< point, 2 > pivot_anchor
Definition: vehicle.h:2310

References map::clear_vehicle_point_from_cache(), get_map(), map::has_flag(), occupied_cache_pos, parts, pivot_anchor, pivot_rotation, pos, TFLAG_RAMP_DOWN, TFLAG_RAMP_UP, and tripoint::z.

Referenced by map::displace_vehicle().

◆ alarm()

void vehicle::alarm ( )

Definition at line 1167 of file vehicle_use.cpp.

1168 {
1169  if( one_in( 4 ) ) {
1170  //first check if the alarm is still installed
1171  bool found_alarm = has_security_working();
1172 
1173  //if alarm found, make noise, else set alarm disabled
1174  if( found_alarm ) {
1175  const std::array<std::string, 4> sound_msgs = {{
1176  _( "WHOOP WHOOP" ), _( "NEEeu NEEeu NEEeu" ), _( "BLEEEEEEP" ), _( "WREEP" )
1177  }
1178  };
1179  sounds::sound( global_pos3(), static_cast<int>( rng( 45, 80 ) ),
1180  sounds::sound_t::alarm, random_entry_ref( sound_msgs ), false, "vehicle", "car_alarm" );
1181  if( one_in( 1000 ) ) {
1182  is_alarm_on = false;
1183  }
1184  } else {
1185  is_alarm_on = false;
1186  }
1187  }
1188 }
time_duration rng(time_duration lo, time_duration hi)
Definition: calendar.cpp:779
bool has_security_working() const
Definition: vehicle.cpp:1038
bool is_alarm_on
Definition: vehicle.h:2358
void sound(const tripoint &p, int vol, sound_t category, const std::string &description, bool ambient=false, const std::string &id="", const std::string &variant="default")
Sound at (p) of intensity (vol)
Definition: sounds.cpp:318
std::enable_if_t< !is_std_array< C >::value, const V & > random_entry_ref(const C &container)
Same as above, but with a statically allocated default value (using the default constructor).
Definition: rng.h:165

References _, sounds::alarm, global_pos3(), has_security_working(), is_alarm_on, one_in(), random_entry_ref(), rng(), and sounds::sound().

Referenced by idle().

◆ all_parts_at_location()

std::vector< int > vehicle::all_parts_at_location ( const std::string &  location) const

Returns all parts in the vehicle that exist in the given location slot.

If the empty string is passed in, returns all parts with no slot.

Parameters
locationThe location slot to get parts for.
Returns
A list of indices to all parts with the specified location.

Definition at line 3075 of file vehicle.cpp.

3076 {
3077  std::vector<int> parts_found;
3078  vehicle_part_range all_parts = get_all_parts();
3079  for( const vpart_reference &vpr : all_parts ) {
3080  if( vpr.info().location == location && !parts[vpr.part_index()].removed ) {
3081  parts_found.push_back( vpr.part_index() );
3082  }
3083  }
3084  return parts_found;
3085 }
static lat_long location
Definition: calendar.cpp:34
A range that contains all parts of the vehicle.
Definition: vpart_range.h:151
vehicle_part_range get_all_parts() const
Yields a range containing all parts (including broken ones) that can be iterated over.
Definition: vehicle.cpp:8119
This is a wrapper over a vehicle pointer and a reference to a part of it.

References get_all_parts(), location, and parts.

Referenced by map::add_vehicle_to_map(), coeff_air_drag(), coeff_water_drag(), veh_interact::display_veh(), find_and_split_vehicles(), merge_rackable_vehicle(), and sufficient_wheel_config().

◆ allow_auto_turn_on_rails()

bool vehicle::allow_auto_turn_on_rails ( units::angle corrected_turn_dir) const

Definition at line 1757 of file vehicle_move.cpp.

1758 {
1759  bool allow_turn_on_rail = false;
1760  // check if autoturn is possible
1761  if( turn_dir == face.dir() ) {
1762  // precalculate wheels for every direction
1763  int straight_wheels_on_rail;
1764  int straight_turning_wheels_that_are_one_axis;
1765  precalculate_vehicle_turning( face.dir(), true, ter_furn_flag::TFLAG_RAIL, straight_wheels_on_rail,
1766  straight_turning_wheels_that_are_one_axis );
1767 
1768  units::angle left_turn_dir =
1769  get_corrected_turn_dir( face.dir() - 45_degrees, face.dir() );
1770  int leftturn_wheels_on_rail;
1771  int leftturn_turning_wheels_that_are_one_axis;
1773  leftturn_wheels_on_rail,
1774  leftturn_turning_wheels_that_are_one_axis );
1775 
1776  units::angle right_turn_dir =
1777  get_corrected_turn_dir( face.dir() + 45_degrees, face.dir() );
1778  int rightturn_wheels_on_rail;
1779  int rightturn_turning_wheels_that_are_one_axis;
1781  rightturn_wheels_on_rail,
1782  rightturn_turning_wheels_that_are_one_axis );
1783 
1784  // if bad terrain ahead (landing wheels num is low)
1785  if( straight_wheels_on_rail <= leftturn_wheels_on_rail &&
1786  is_wheel_state_correct_to_turn_on_rails( leftturn_wheels_on_rail, rail_wheelcache.size(),
1787  leftturn_turning_wheels_that_are_one_axis ) ) {
1788  allow_turn_on_rail = true;
1789  corrected_turn_dir = left_turn_dir;
1790  } else if( straight_wheels_on_rail <= rightturn_wheels_on_rail &&
1791  is_wheel_state_correct_to_turn_on_rails( rightturn_wheels_on_rail, rail_wheelcache.size(),
1792  rightturn_turning_wheels_that_are_one_axis ) ) {
1793  allow_turn_on_rail = true;
1794  corrected_turn_dir = right_turn_dir;
1795  }
1796  }
1797  return allow_turn_on_rail;
1798 }
std::vector< int > rail_wheelcache
Definition: vehicle.h:2185
void precalculate_vehicle_turning(units::angle new_turn_dir, bool check_rail_direction, ter_furn_flag ter_flag_to_check, int &wheels_on_rail, int &turning_wheels_that_are_one_axis_counter) const
Precalculate vehicle turn.
bool is_wheel_state_correct_to_turn_on_rails(int wheels_on_rail, int wheel_count, int turning_wheels_that_are_one_axis) const
static units::angle get_corrected_turn_dir(const units::angle &turn_dir, const units::angle &face_dir)

References tileray::dir(), face, get_corrected_turn_dir(), is_wheel_state_correct_to_turn_on_rails(), precalculate_vehicle_turning(), rail_wheelcache, TFLAG_RAIL, and turn_dir.

Referenced by act_on_map().

◆ allow_manual_turn_on_rails()

bool vehicle::allow_manual_turn_on_rails ( units::angle corrected_turn_dir) const

Definition at line 1738 of file vehicle_move.cpp.

1739 {
1740  bool allow_turn_on_rail = false;
1741  // driver tried to turn rails vehicle
1742  if( turn_dir != face.dir() ) {
1743  corrected_turn_dir = get_corrected_turn_dir( turn_dir, face.dir() );
1744 
1745  int wheels_on_rail;
1746  int turning_wheels_that_are_one_axis;
1747  precalculate_vehicle_turning( corrected_turn_dir, true, ter_furn_flag::TFLAG_RAIL, wheels_on_rail,
1748  turning_wheels_that_are_one_axis );
1749  if( is_wheel_state_correct_to_turn_on_rails( wheels_on_rail, rail_wheelcache.size(),
1750  turning_wheels_that_are_one_axis ) ) {
1751  allow_turn_on_rail = true;
1752  }
1753  }
1754  return allow_turn_on_rail;
1755 }

References tileray::dir(), face, get_corrected_turn_dir(), is_wheel_state_correct_to_turn_on_rails(), precalculate_vehicle_turning(), rail_wheelcache, TFLAG_RAIL, and turn_dir.

Referenced by act_on_map().

◆ assign_seat()

bool vehicle::assign_seat ( vehicle_part pt,
const npc who 
)

Try to assign a crew member (who must be a player ally) to a specific seat.

Note
enforces NPC's being assigned to only one seat (per-vehicle) at once

Definition at line 693 of file vehicle_part.cpp.

694 {
695  if( !pt.is_seat() || !pt.set_crew( who ) ) {
696  return false;
697  }
698 
699  // NPC's can only be assigned to one seat in the vehicle
700  for( vehicle_part &e : parts ) {
701  if( &e == &pt ) {
702  // skip this part
703  continue;
704  }
705 
706  if( e.is_seat() ) {
707  const npc *n = e.crew();
708  if( n && n->getID() == who.getID() ) {
709  e.unset_crew();
710  }
711  }
712  }
713 
714  return true;
715 }
character_id getID() const
Definition: character.cpp:652
Definition: npc.h:792
bool is_seat() const
Can a player or NPC use this part as a seat?
bool set_crew(const npc &who)
Set crew member for this part (seat, turret etc) who must be a player ally)

References Character::getID(), vehicle_part::is_seat(), parts, and vehicle_part::set_crew().

Referenced by veh_interact::do_assign_crew().

◆ auto_select_fuel()

bool vehicle::auto_select_fuel ( vehicle_part vp)

Definition at line 611 of file vehicle_use.cpp.

612 {
613  const vpart_info &vp_engine_info = vp.info();
614  if( !vp.is_available() || !vp.is_engine() ) {
615  return false;
616  }
617  if( vp_engine_info.fuel_type == fuel_type_none || engine_fuel_left( vp ) > 0 ) {
618  return true;
619  }
620  for( const itype_id &fuel_id : vp_engine_info.engine_info->fuel_opts ) {
621  if( fuel_left( fuel_id ) > 0 ) {
622  vp.fuel_set( fuel_id );
623  return true;
624  }
625  }
626  return false; // not a single fuel type left for this engine
627 }
int64_t fuel_left(const itype_id &ftype, const std::function< bool(const vehicle_part &)> &filter=return_true< const vehicle_part & >) const
Definition: vehicle.cpp:3516
int engine_fuel_left(const vehicle_part &vp) const
Definition: vehicle.cpp:3576
std::optional< vpslot_engine > engine_info
Definition: veh_type.h:296
bool fuel_set(const itype_id &fuel)
Set an engine to use a different type of fuel.
bool is_engine() const
Can this part provide power or propulsion?
static const itype_id fuel_type_none("null")

References engine_fuel_left(), vpart_info::engine_info, fuel_left(), vehicle_part::fuel_set(), vpart_info::fuel_type, fuel_type_none, vehicle_part::info(), vehicle_part::is_available(), and vehicle_part::is_engine().

Referenced by init_state(), and start_engine().

◆ automatic_fire_turret()

int vehicle::automatic_fire_turret ( vehicle_part pt)

Definition at line 573 of file turret.cpp.

574 {
575  turret_data gun = turret_query( pt );
576 
577  int shots = 0;
578 
579  if( gun.query() != turret_data::status::ready ) {
580  return shots;
581  }
582 
583  // The position of the vehicle part.
584  tripoint pos = global_part_pos3( pt );
585 
586  // Create the targeting computer's npc
587  npc &cpu = pt.get_targeting_npc( *this );
588 
589  int area = max_aoe_size( gun.ammo_effects() );
590  if( area > 0 ) {
591  // Pad a bit for less friendly fire
592  area += area == 1 ? 1 : 2;
593  }
594 
595  Character &player_character = get_player_character();
596  const bool u_see = player_character.sees( pos );
597  const bool u_hear = !player_character.is_deaf();
598  // The current target of the turret.
599  auto &target = pt.target;
600  if( target.first == target.second ) {
601  // Manual target not set, find one automatically.
602  // BEWARE: Calling turret_data.fire on tripoint min coordinates starts a crash
603  // triggered at `trajectory.insert( trajectory.begin(), source )` at ranged.cpp:236
604  pt.reset_target( pos );
605  int boo_hoo;
606 
607  // TODO: calculate chance to hit and cap range based upon this
608  int max_range = 20;
609  int range = std::min( gun.range(), max_range );
610  Creature *auto_target = cpu.auto_find_hostile_target( range, boo_hoo, area );
611  if( auto_target == nullptr ) {
612  if( boo_hoo ) {
613  cpu.get_name() = string_format( pgettext( "vehicle turret", "The %s" ), pt.name() );
614  // check if the player can see or hear then print chooses a message accordingly
615  if( u_see & u_hear ) {
616  add_msg( m_warning, n_gettext( "%s points in your direction and emits an IFF warning beep.",
617  "%s points in your direction and emits %d annoyed sounding beeps.",
618  boo_hoo ),
619  cpu.get_name(), boo_hoo );
620  } else if( !u_see & u_hear ) {
621  add_msg( m_warning, n_gettext( "You hear a warning beep.",
622  "You hear %d annoyed sounding beeps.",
623  boo_hoo ), boo_hoo );
624  } else if( u_see & !u_hear ) {
625  add_msg( m_warning, _( "%s points in your direction." ), cpu.get_name() );
626  }
627  }
628  return shots;
629  }
630 
631  target.second = auto_target->pos();
632 
633  } else {
634  // Target is already set, make sure we didn't move after aiming (it's a bug if we did).
635  if( pos != target.first ) {
636  target.second = target.first;
637  debugmsg( "%s moved after aiming but before it could fire.", cpu.get_name() );
638  return shots;
639  }
640  }
641 
642  // Get the turret's target and reset it
643  tripoint targ = target.second;
644  pt.reset_target( pos );
645 
646  shots = gun.fire( cpu, targ );
647 
648  if( shots && u_see ) {
649  add_msg_if_player_sees( targ, _( "The %1$s fires its %2$s!" ), name, pt.name() );
650  }
651 
652  return shots;
653 }
bool sees(const tripoint &t, bool is_avatar=false, int range_mod=0) const override
std::string get_name() const override
Definition: character.cpp:5731
bool is_deaf() const
Definition: character.cpp:4614
tripoint pos() const
Definition: creature.cpp:178
Creature * auto_find_hostile_target(int range, int &boo_hoo, int area=0)
For fake-players (turrets, mounted turrets) this functions chooses a target.
Definition: creature.cpp:554
turret_data turret_query(vehicle_part &pt)
Get firing data for a turret.
Definition: turret.cpp:60
@ m_warning
Definition: enums.h:351
void add_msg_if_player_sees(const tripoint &target, std::string msg)
Definition: messages.cpp:1007
int max_aoe_size(const std::set< std::string > &tags)
Definition: projectile.cpp:191
std::string string_format(std::string_view format, Args &&...args)
Simple wrapper over string_formatter::parse.
std::string name(bool with_prefix=true) const
Translated name of a part inclusive of any current status effects with_prefix as true indicates the d...
std::pair< tripoint, tripoint > target
Coordinates for some kind of target; jumper cables and turrets use this Two coordinate pairs are stor...
Definition: vehicle.h:526
npc & get_targeting_npc(vehicle &veh)
Definition: turret.cpp:547
void reset_target(const tripoint &pos)
Reset the target for this part.
#define n_gettext(STRING1, STRING2, COUNT)
Definition: translations.h:91
#define pgettext(STRING1, STRING2)
Definition: translations.h:92

References _, add_msg(), add_msg_if_player_sees(), Creature::auto_find_hostile_target(), debugmsg, Character::get_name(), get_player_character(), vehicle_part::get_targeting_npc(), global_part_pos3(), gun, Character::is_deaf(), m_warning, max_aoe_size(), min(), n_gettext, vehicle_part::name(), name, pgettext, Creature::pos(), pos, turret_data::ready, vehicle_part::reset_target(), Character::sees(), string_format(), vehicle_part::target, and turret_query().

Referenced by gain_moves().

◆ autopilot_patrol()

void vehicle::autopilot_patrol ( )

choose one single zone ( multiple zones too complex for now ) choose a point at the far edge of the zone the edge chosen is the edge that is smaller, therefore the longer side of the rectangle is the one the vehicle drives mostly parallel too. if its perfect square then choose a point that is on any edge that the vehicle is not currently at drive to that point. then once arrived, choose a random opposite point of the zone. this should ( in a simple fashion ) cause a patrolling behavior in a criss-cross fashion. in an auto-tractor, this would eventually cover the entire rectangle.

Definition at line 614 of file vehicle.cpp.

615 {
616  /** choose one single zone ( multiple zones too complex for now )
617  * choose a point at the far edge of the zone
618  * the edge chosen is the edge that is smaller, therefore the longer side
619  * of the rectangle is the one the vehicle drives mostly parallel too.
620  * if its perfect square then choose a point that is on any edge that the
621  * vehicle is not currently at
622  * drive to that point.
623  * then once arrived, choose a random opposite point of the zone.
624  * this should ( in a simple fashion ) cause a patrolling behavior
625  * in a criss-cross fashion.
626  * in an auto-tractor, this would eventually cover the entire rectangle.
627  */
628  map &here = get_map();
629  // if we are close to a waypoint, then return to come back to this function next turn.
631  if( rl_dist( global_square_location().raw(), autodrive_local_target ) <= 3 ) {
633  return;
634  }
635  if( !here.inbounds( here.getlocal( autodrive_local_target ) ) ) {
637  is_patrolling = false;
638  return;
639  }
641  return;
642  }
644  const auto &zone_src_set =
646  if( zone_src_set.empty() ) {
647  is_patrolling = false;
648  return;
649  }
650  // get corners.
653  for( const tripoint_abs_ms &box : zone_src_set ) {
654  if( min == tripoint_abs_ms() ) {
655  min = box;
656  max = box;
657  continue;
658  }
659  min.x() = std::min( box.x(), min.x() );
660  min.y() = std::min( box.y(), min.y() );
661  min.z() = std::min( box.z(), min.z() );
662  max.x() = std::max( box.x(), max.x() );
663  max.y() = std::max( box.y(), max.y() );
664  max.z() = std::max( box.z(), max.z() );
665  }
666  const bool x_side = ( max.x() - min.x() ) < ( max.y() - min.y() );
667  const int point_along = x_side ? rng( min.x(), max.x() ) : rng( min.y(), max.y() );
668  const tripoint_abs_ms max_tri = x_side ? tripoint_abs_ms( point_along, max.y(), min.z() ) :
669  tripoint_abs_ms( max.x(), point_along, min.z() );
670  const tripoint_abs_ms min_tri = x_side ? tripoint_abs_ms( point_along, min.y(), min.z() ) :
671  tripoint_abs_ms( min.x(), point_along, min.z() );
672  tripoint_abs_ms chosen_tri = min_tri;
673  if( rl_dist( max_tri, global_square_location() ) >=
674  rl_dist( min_tri, global_square_location() ) ) {
675  chosen_tri = max_tri;
676  }
677  // TODO: fix point types
678  autodrive_local_target = chosen_tri.raw();
680 }
constexpr const Point & raw() const
Definition: coordinates.h:157
tripoint getlocal(const tripoint &p) const
Inverse of getabs.
Definition: map.cpp:9635
tripoint_abs_ms global_square_location() const
Definition: vehicle.cpp:3421
bool is_patrolling
Definition: vehicle.h:2349
void drive_to_local_target(const tripoint &target, bool follow_protocol)
Definition: vehicle.cpp:730
tripoint autodrive_local_target
Definition: vehicle.h:2244
std::unordered_set< tripoint_abs_ms > get_near(const zone_type_id &type, const tripoint_abs_ms &where, int range=MAX_DISTANCE, const item *it=nullptr, const faction_id &fac=your_fac) const
Definition: clzones.cpp:1134
static zone_manager & get_manager()
Definition: clzones.h:550
coords::coord_point< tripoint, coords::origin::abs, coords::ms > tripoint_abs_ms
Definition: coordinates.h:712
int rl_dist(const coords::coord_point< Point, Origin, Scale, LhsInBounds > &loc1, const coords::coord_point< Point, Origin, Scale, RhsInBounds > &loc2)
Definition: coordinates.h:769
double max(std::vector< double > const &params)
constexpr tripoint tripoint_zero
Definition: point.h:250
static const zone_type_id zone_type_VEHICLE_PATROL("VEHICLE_PATROL")

References autodrive_local_target, drive_to_local_target(), zone_manager::get_manager(), get_map(), zone_manager::get_near(), map::getlocal(), global_square_location(), map::inbounds(), is_patrolling, max(), min(), coords::coord_point_mut< Point, Subpoint, InBounds >::raw(), rl_dist(), rng(), tripoint_zero, and zone_type_VEHICLE_PATROL.

Referenced by map::vehmove().

◆ autopilot_patrol_check()

void vehicle::autopilot_patrol_check ( )

Definition at line 485 of file vehicle_use.cpp.

486 {
489  enable_patrol();
490  } else {
491  g->zones_manager();
492  }
493 }
void enable_patrol()
bool has_near(const zone_type_id &type, const tripoint_abs_ms &where, int range=MAX_DISTANCE, const faction_id &fac=your_fac) const
Definition: clzones.cpp:1011
static const zone_type_id zone_type_VEHICLE_PATROL("VEHICLE_PATROL")

References enable_patrol(), g, zone_manager::get_manager(), global_square_location(), zone_manager::has_near(), and zone_type_VEHICLE_PATROL.

Referenced by toggle_autopilot().

◆ avail_linkable_part()

int vehicle::avail_linkable_part ( const point pt,
bool  to_ports 
) const

Returns index of part at mount point pt which has link connection and is_available(), or -1 if no such part or it's not is_available()

Note
does not use relative_parts cache
Parameters
ptonly returns parts from this mount point
to_portsif true, look for part with CABLE_PORTS flag. If false, BATTERY. Either way, will also look for APPLIANCE
Returns
part index or -1

Definition at line 2814 of file vehicle.cpp.

2815 {
2816  const std::string link_flag = to_ports ? "CABLE_PORTS" : "BATTERY";
2817  for( const int p : parts_at_relative( pt, /* use_cache = */ false ) ) {
2818  const vehicle_part &vp_here = this->part( p );
2819  if( !vp_here.is_broken() &&
2820  ( vp_here.info().has_flag( "APPLIANCE" ) || vp_here.info().has_flag( link_flag ) ) ) {
2821  return p;
2822  }
2823  }
2824  return -1;
2825 }
vehicle_part & part(int part_num)
Definition: vehicle.cpp:8098
std::vector< int > parts_at_relative(const point &dp, bool use_cache, bool include_fake=false) const
Definition: vehicle.cpp:2569

References vpart_info::has_flag(), vehicle_part::info(), vehicle_part::is_broken(), part(), and parts_at_relative().

Referenced by item::link_to().

◆ avail_part_with_feature() [1/2]

int vehicle::avail_part_with_feature ( const point pt,
const std::string &  f 
) const

Returns index of part at mount point pt which has given f flag and is_available(), or -1 if no such part or it's not is_available()

Note
does not use relative_parts cache
Parameters
ptonly returns parts from this mount point
frequired flag in part's vpart_info flags collection
unbrokenif true also requires the part to be !is_broken
Returns
part index or -1

Definition at line 2805 of file vehicle.cpp.

2806 {
2807  const int part_a = part_with_feature( pt, flag, true );
2808  if( ( part_a >= 0 ) && this->part( part_a ).is_available() ) {
2809  return part_a;
2810  }
2811  return -1;
2812 }

References part(), and part_with_feature().

Referenced by vpart_position::avail_part_with_feature(), game::control_vehicle(), and fuel_left().

◆ avail_part_with_feature() [2/2]

int vehicle::avail_part_with_feature ( int  p,
vpart_bitflags  f 
) const

Returns p or part index at mount point pt which has given f flag and is_available(), or -1 if no such part or it's not is_available()

Note
uses relative_parts cache
Parameters
pindex of part to start searching from
frequired flag in part's vpart_info flags collection
unbrokenif true also requires the part to be !is_broken()
Returns
part index or -1

Definition at line 2796 of file vehicle.cpp.

2797 {
2798  const int part_a = part_with_feature( part, flag, true );
2799  if( ( part_a >= 0 ) && this->part( part_a ).is_available() ) {
2800  return part_a;
2801  }
2802  return -1;
2803 }

References part(), and part_with_feature().

◆ average_offroad_rating()

float vehicle::average_offroad_rating ( ) const

Definition at line 4115 of file vehicle.cpp.

4116 {
4117  if( wheelcache.empty() ) {
4118  return 0.0f;
4119  }
4120  float total_rating = 0.0f;
4121  for( const int wheel_index : wheelcache ) {
4122  const vehicle_part &vp = part( wheel_index );
4123  total_rating += vp.info().wheel_info->offroad_rating;
4124  }
4125  return total_rating / wheelcache.size();
4126 }
std::vector< int > wheelcache
Definition: vehicle.h:2183
std::optional< vpslot_wheel > wheel_info
Definition: veh_type.h:297

References vehicle_part::info(), part(), vpart_info::wheel_info, and wheelcache.

Referenced by veh_interact::display_stats(), and overmap_ui::get_overmap_path_to().

◆ backfire()

void vehicle::backfire ( const vehicle_part vp) const

Definition at line 1064 of file vehicle.cpp.

1065 {
1066  // single space after the exclamation mark because it does not end the sentence
1067  //~ backfire sound
1068  const std::string text = _( "a loud BANG! from the %s" ); // NOLINT(cata-text-style);
1069  const tripoint pos = global_part_pos3( vp );
1070  const int volume = 40 + units::to_watt( part_vpower_w( vp, true ) ) / 10000;
1072  string_format( text, vp.name() ), true, "vehicle", "engine_backfire" );
1073 }
units::power part_vpower_w(const vehicle_part &vp, bool at_full_hp=false) const
Definition: vehicle.cpp:1077
quantity< int, volume_in_milliliter_tag > volume
Definition: units_fwd.h:17
constexpr value_type to_watt(const quantity< value_type, power_in_milliwatt_tag > &v)
Definition: units.h:626

References _, global_part_pos3(), sounds::movement, vehicle_part::name(), part_vpower_w(), pos, sounds::sound(), string_format(), and units::to_watt().

Referenced by noise_and_smoke(), and start_engine().

◆ balanced_wheel_config()

bool vehicle::balanced_wheel_config ( ) const

Definition at line 4745 of file vehicle.cpp.

4746 {
4747  point min = point_max;
4748  point max = point_min;
4749  // find the bounding box of the wheels
4750  for( const int &w : wheelcache ) {
4751  const point &pt = parts[ w ].mount;
4752  min.x = std::min( min.x, pt.x );
4753  min.y = std::min( min.y, pt.y );
4754  max.x = std::max( max.x, pt.x );
4755  max.y = std::max( max.y, pt.y );
4756  }
4757 
4758  // Check center of mass inside support of wheels (roughly)
4759  const point &com = local_center_of_mass();
4760  const inclusive_rectangle<point> support( min, max );
4761  return support.contains( com );
4762 }
const point & local_center_of_mass() const
Definition: vehicle.cpp:3492
constexpr point point_min
Definition: point.h:296
constexpr point point_max
Definition: point.h:297
Definition: point.h:20
int y
Definition: point.h:24
int x
Definition: point.h:23

References inclusive_rectangle< Point, >::contains(), local_center_of_mass(), max(), min(), parts, point_max, point_min, wheelcache, point::x, and point::y.

Referenced by valid_wheel_config(), and wheel_state_description().

◆ basic_consumption()

units::power vehicle::basic_consumption ( const itype_id ftype) const

Definition at line 3664 of file vehicle.cpp.

3665 {
3666  units::power fcon = 0_W;
3667  for( const int p : engines ) {
3668  const vehicle_part &vp = parts[p];
3669  if( !is_engine_type_on( vp, ftype ) ) {
3670  continue;
3671  }
3672  if( vp.ammo_current() == fuel_type_battery && part_epower( vp ) >= 0_W ) {
3673  fcon -= part_epower( vp ); // Electric engine - use epower instead
3674  } else if( !is_perpetual_type( vp ) ) {
3675  fcon += part_vpower_w( vp );
3676  if( vp.has_fault_flag( "DOUBLE_FUEL_CONSUMPTION" ) ) {
3677  fcon *= 2;
3678  }
3679  }
3680  }
3681  return fcon;
3682 }
bool is_engine_type_on(const vehicle_part &vp, const itype_id &ft) const
Definition: vehicle.cpp:952
bool is_perpetual_type(const vehicle_part &vp) const
Definition: vehicle.cpp:1010
std::vector< int > engines
Definition: vehicle.h:2173
bool has_fault_flag(const std::string &searched_flag) const
Does this vehicle part have a fault with this flag.
itype_id ammo_current() const
Specific type of fuel, charges or ammunition currently contained by a part.
static const itype_id fuel_type_battery("battery")

References vehicle_part::ammo_current(), engines, fuel_type_battery, vehicle_part::has_fault_flag(), is_engine_type_on(), is_perpetual_type(), part_epower(), part_vpower_w(), and parts.

◆ battery_left()

int64_t vehicle::battery_left ( bool  apply_loss = true) const
Parameters
apply_lossif true apply wire loss when charge crosses vehicle power cables
Returns
battery charge in kJ from all connected batteries

Definition at line 5507 of file vehicle.cpp.

5508 {
5509  int64_t ret = 0;
5510  for( const std::pair<const vehicle *const, float> &pair : search_connected_vehicles() ) {
5511  const vehicle &veh = *pair.first;
5512  const float efficiency = 1.0f - ( apply_loss ? pair.second : 0.0f );
5513  for( const int part_idx : veh.batteries ) {
5514  const vehicle_part &vp = veh.parts[part_idx];
5515  ret += vp.ammo_remaining() * efficiency;
5516  }
5517  }
5518  return ret;
5519 }
A vehicle as a whole with all its components.
Definition: vehicle.h:802
std::map< vehicle *, float > search_connected_vehicles()
Returns a map of connected vehicle pointers to power loss factor: Keys are vehicles connected by POWE...
Definition: vehicle.cpp:5413
std::vector< int > batteries
Definition: vehicle.h:2190

References vehicle_part::ammo_remaining(), batteries, parts, cata::hash64_detail::ret, and search_connected_vehicles().

Referenced by power_parts(), and tool_ammo_available().

◆ battery_power_level()

std::pair< int, int > vehicle::battery_power_level ( ) const

Definition at line 5010 of file vehicle.cpp.

5011 {
5012  int total_epower_capacity = 0;
5013  int remaining_epower = 0;
5014 
5015  for( const int bi : batteries ) {
5016  const vehicle_part &b = parts[bi];
5017  if( b.is_available() ) {
5018  remaining_epower += b.ammo_remaining();
5019  total_epower_capacity += b.ammo_capacity( ammo_battery );
5020  }
5021  }
5022 
5023  return std::make_pair( remaining_epower, total_epower_capacity );
5024 }
static constexpr double b
Definition: magic.cpp:1567
static const ammotype ammo_battery("battery")

References ammo_battery, b, batteries, and parts.

Referenced by veh_app_interact::draw_info(), and smart_controller_handle_turn().

◆ beeper_sound()

void vehicle::beeper_sound ( ) const

Definition at line 917 of file vehicle_use.cpp.

918 {
919  // No power = no sound
920  if( fuel_left( fuel_type_battery ) == 0 ) {
921  return;
922  }
923 
924  const bool odd_turn = calendar::once_every( 2_turns );
925  for( const vpart_reference &vp : get_avail_parts( "BEEPER" ) ) {
926  if( ( odd_turn && vp.has_feature( VPFLAG_EVENTURN ) ) ||
927  ( !odd_turn && vp.has_feature( VPFLAG_ODDTURN ) ) ) {
928  continue;
929  }
930 
931  //~ Beeper sound
932  sounds::sound( vp.pos(), vp.info().bonus, sounds::sound_t::alarm, _( "beep!" ), false, "vehicle",
933  "rear_beeper" );
934  }
935 }
vehicle_part_with_feature_range< std::string > get_avail_parts(std::string feature) const
Yields a range of parts of this vehicle that each have the given feature and are available: not broke...
Definition: vehicle.cpp:3007
bool once_every(const time_duration &event_frequency)
Predicate to handle rate-limiting.
Definition: calendar.cpp:753
@ VPFLAG_EVENTURN
Definition: veh_type.h:61
@ VPFLAG_ODDTURN
Definition: veh_type.h:62
static const itype_id fuel_type_battery("battery")

References _, sounds::alarm, fuel_left(), fuel_type_battery, get_avail_parts(), calendar::once_every(), sounds::sound(), VPFLAG_EVENTURN, and VPFLAG_ODDTURN.

Referenced by gain_moves().

◆ boarded_parts()

std::vector< int > vehicle::boarded_parts ( ) const

Definition at line 3362 of file vehicle.cpp.

3363 {
3364  std::vector<int> res;
3365  for( const vpart_reference &vp : get_avail_parts( VPFLAG_BOARDABLE ) ) {
3366  if( vp.part().has_flag( vp_flag::passenger_flag ) ) {
3367  res.push_back( static_cast<int>( vp.part_index() ) );
3368  }
3369  }
3370  return res;
3371 }
@ VPFLAG_BOARDABLE
Definition: veh_type.h:67
@ passenger_flag

References get_avail_parts(), passenger_flag, and VPFLAG_BOARDABLE.

Referenced by act_on_map(), is_passenger(), and unboard_all().

◆ break_off()

int vehicle::break_off ( map here,
vehicle_part vp,
int  dmg 
)
private

Definition at line 7311 of file vehicle.cpp.

7312 {
7313  const vpart_info &vpi = vp.info();
7314  /* Already-destroyed part - chance it could be torn off into pieces.
7315  * Chance increases with damage, and decreases with part max durability
7316  * (so lights, etc are easily removed; frames and plating not so much) */
7317  if( rng( 0, vpi.durability / 10 ) >= dmg ) {
7318  return dmg;
7319  }
7320  const tripoint pos = global_part_pos3( vp );
7321  const auto scatter_parts = [&]( const vehicle_part & pt ) {
7322  for( const item &piece : pt.pieces_for_broken_part() ) {
7323  // inside the loop, so each piece goes to a different place
7324  // TODO: this may spawn items behind a wall
7325  const tripoint where = random_entry( here.points_in_radius( pos, SCATTER_DISTANCE ) );
7326  // TODO: balance audit, ensure that less pieces are generated than one would need
7327  // to build the component (smash a vehicle box that took 10 lumps of steel,
7328  // find 12 steel lumps scattered after atom-smashing it with a tree trunk)
7329  if( !magic ) {
7330  here.add_item_or_charges( where, piece );
7331  }
7332  }
7333  };
7334  std::unique_ptr<RemovePartHandler> handler_ptr;
7335  if( g && &get_map() == &here ) {
7336  handler_ptr = std::make_unique<DefaultRemovePartHandler>();
7337  } else {
7338  handler_ptr = std::make_unique<MapgenRemovePartHandler>( here );
7339  }
7340  if( vpi.location == part_location_structure ) {
7341  // For structural parts, remove other parts first
7342  std::vector<int> parts_in_square = parts_at_relative( vp.mount, true );
7343  for( int index = parts_in_square.size() - 1; index >= 0; index-- ) {
7344  vehicle_part &vp_here = parts[parts_in_square[index]];
7345  const vpart_info &vpi_here = vp_here.info();
7346  if( &vp_here == &vp ) {
7347  continue; // Ignore the frame being destroyed
7348  } else if( vpi_here.has_flag( "TOW_CABLE" ) ) {
7349  // Tow cables - remove it in one piece, remove remote part, and remove towing data
7350  add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is disconnected!" ), name, vp_here.name() );
7351  invalidate_towing( true );
7352  } else if( vpi_here.has_flag( VPFLAG_POWER_TRANSFER ) ) {
7353  // Electrical cables - remove it in one piece and remove remote part
7354  add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is disconnected!" ), name, vp_here.name() );
7355  here.add_item_or_charges( pos, part_to_item( vp_here ) );
7356  remove_remote_part( vp_here );
7357  } else if( vp_here.is_broken() ) {
7358  // Tearing off a broken part - break it up
7359  add_msg_if_player_sees( pos, m_bad, _( "The %s's %s breaks into pieces!" ), name, vp_here.name() );
7360  scatter_parts( vp_here );
7361  } else {
7362  // Intact (but possibly damaged) part - remove it in one piece
7363  add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is torn off!" ), name, vp_here.name() );
7364  if( !magic ) {
7365  here.add_item_or_charges( pos, part_to_item( vp_here ) );
7366  }
7367  }
7368  remove_part( vp_here, *handler_ptr );
7369  }
7370  // After clearing the frame, remove it.
7371  add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is destroyed!" ), name, vp.name() );
7372  scatter_parts( vp );
7373  remove_part( vp, *handler_ptr );
7374  find_and_split_vehicles( here, { index_of_part( &vp, /* include_removed = */ true ) } );
7375  } else {
7376  if( vpi.has_flag( "TOW_CABLE" ) ) {
7377  // Tow cables - remove it in one piece, remove remote part, and remove towing data
7378  add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is disconnected!" ), name, vp.name() );
7379  invalidate_towing( true );
7380  } else if( vpi.has_flag( VPFLAG_POWER_TRANSFER ) ) {
7381  // Electrical cables - remove it in one piece and remove remote part
7382  add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is disconnected!" ), name, vp.name() );
7383  here.add_item_or_charges( pos, part_to_item( vp ) );
7384  remove_remote_part( vp );
7385  } else {
7386  //Just break it off
7387  add_msg_if_player_sees( pos, m_bad, _( "The %1$s's %2$s is destroyed!" ), name, vp.name() );
7388  scatter_parts( vp );
7389  }
7390  const point position = vp.mount;
7391  remove_part( vp, *handler_ptr );
7392 
7393  // remove parts for which required flags are not present anymore
7394  if( !vpi.get_flags().empty() ) {
7395  const std::vector<int> parts_here = parts_at_relative( position, false );
7396  for( const int part : parts_here ) {
7397  vehicle_part &vp_here = parts[part];
7398  const vpart_info &vpi_here = vp_here.info();
7399  bool remove = false;
7400  for( const std::string &flag : vpi_here.get_flags() ) {
7401  const std::string &required_flag = json_flag::get( flag ).requires_flag();
7402  if( !required_flag.empty() ) {
7403  remove = true;
7404  for( const int elem : parts_here ) {
7405  if( parts[elem].info().has_flag( required_flag ) ) {
7406  remove = false;
7407  continue;
7408  }
7409  }
7410  }
7411  }
7412  if( remove ) {
7413  if( vpi_here.has_flag( "TOW_CABLE" ) ) {
7414  invalidate_towing( true );
7415  } else {
7416  if( vpi_here.has_flag( VPFLAG_POWER_TRANSFER ) ) {
7417  remove_remote_part( vp_here );
7418  }
7419  here.add_item_or_charges( pos, part_to_item( vp_here ) );
7420  remove_part( vp_here, *handler_ptr );
7421  }
7422  }
7423  }
7424  }
7425  }
7426 
7427  return dmg;
7428 }
const std::string & requires_flag() const
Requires this flag to be installed on vehicle.
Definition: flag.h:448
static const json_flag & get(const std::string &id)
Fetches flag definition (or null flag if not found)
Definition: flag.cpp:404
tripoint_range< tripoint > points_in_radius(const tripoint &center, size_t radius, size_t radiusz=0) const
Definition: map.cpp:10109
item & add_item_or_charges(const tripoint &pos, item obj, bool overflow=true)
Definition: map.cpp:5177
bool find_and_split_vehicles(map &here, std::set< int > exclude)
Definition: vehicle.cpp:2275
bool magic
Definition: vehicle.h:2219
int index_of_part(const vehicle_part *part, bool include_removed=false) const
Definition: vehicle.cpp:3224
void invalidate_towing(bool first_vehicle=false, Character *remover=nullptr)
Definition: vehicle.cpp:6828
item part_to_item(const vehicle_part &vp) const
Generate the corresponding item from this vehicle part.
Definition: vehicle.cpp:8223
void remove_remote_part(const vehicle_part &vp_local) const
Remove the part on a targeted remote vehicle that a part is targeting.
Definition: vehicle.cpp:6966
bool remove_part(vehicle_part &vp)
Mark a part as removed from the vehicle.
Definition: vehicle.cpp:1966
std::string location
What slot of the vehicle tile does this part occupy?
Definition: veh_type.h:406
const std::set< std::string > & get_flags() const
Definition: veh_type.h:253
int durability
Maximum damage part can sustain before being destroyed.
Definition: veh_type.h:409
V random_entry(const C &container, D default_value)
Returns a random entry in the container.
Definition: rng.h:104
@ VPFLAG_POWER_TRANSFER
Definition: veh_type.h:113
static const std::string part_location_structure("structure")
constexpr int SCATTER_DISTANCE
Definition: vehicle.h:95

References _, map::add_item_or_charges(), add_msg_if_player_sees(), vpart_info::durability, find_and_split_vehicles(), g, json_flag::get(), vpart_info::get_flags(), get_map(), global_part_pos3(), vpart_info::has_flag(), index_of_part(), vehicle_part::info(), invalidate_towing(), vehicle_part::is_broken(), vpart_info::location, m_bad, magic, vehicle_part::mount, vehicle_part::name(), name, part(), part_location_structure(), part_to_item(), parts, parts_at_relative(), map::points_in_radius(), pos, random_entry(), remove, remove_part(), remove_remote_part(), json_flag::requires_flag(), rng(), SCATTER_DISTANCE, and VPFLAG_POWER_TRANSFER.

Referenced by damage_direct().

◆ bub_part_pos() [1/2]

tripoint_bub_ms vehicle::bub_part_pos ( const vehicle_part pt) const

Definition at line 3457 of file vehicle.cpp.

3458 {
3459  return pos_bub() + pt.precalc[ 0 ];
3460 }
tripoint_bub_ms pos_bub() const
Definition: vehicle.cpp:3436
std::array< tripoint, 2 > precalc
mount translated to face.dir [0] and turn_dir [1]
Definition: vehicle.h:451

References pos_bub(), and vehicle_part::precalc.

◆ bub_part_pos() [2/2]

tripoint_bub_ms vehicle::bub_part_pos ( int  index) const

◆ build_bike_rack_menu()

void vehicle::build_bike_rack_menu ( veh_menu menu,
int  part 
)

Definition at line 1639 of file vehicle_use.cpp.

1640 {
1641  // prevent racking two vehicles with same name on single vehicle
1642  // @returns true if vehicle already has a vehicle with this name racked
1643  const auto has_veh_name_racked = [this]( const std::string & name ) {
1644  for( const vpart_reference &vpr : get_any_parts( "BIKE_RACK_VEH" ) ) {
1645  for( const unrackable_vehicle &unrackable : find_vehicles_to_unrack( vpr.part_index() ) ) {
1646  if( unrackable.name == name ) {
1647  return true;
1648  }
1649  }
1650  }
1651  return false;
1652  };
1653 
1654  menu.desc_lines_hint = std::max( 1, menu.desc_lines_hint );
1655  bool has_rack_actions = false;
1656 
1657  for( const rackable_vehicle &rackable : find_vehicles_to_rack( part ) ) {
1658  const bool has_this_name_racked = has_veh_name_racked( rackable.name );
1659 
1660  menu.add( string_format( _( "Attach the %s to the rack" ), rackable.name ) )
1661  .desc( has_this_name_racked
1662  ? string_format( _( "This vehicle already has '%s' racked. "
1663  "Please rename before racking." ), rackable.name )
1664  : "" )
1665  .enable( !has_this_name_racked )
1666  .hotkey_auto()
1668  .on_submit( [this, rackable] {
1669  bikerack_racking_activity_actor rack( *this, *rackable.veh, rackable.racks );
1671  } );
1672 
1673  has_rack_actions = true;
1674  }
1675 
1676  for( const unrackable_vehicle &unrackable : find_vehicles_to_unrack( part ) ) {
1677  menu.add( string_format( _( "Remove the %s from the rack" ), unrackable.name ) )
1678  .hotkey_auto()
1680  .on_submit( [this, unrackable] {
1681  bikerack_unracking_activity_actor unrack( *this, unrackable.parts, unrackable.racks );
1683  } );
1684 
1685  has_rack_actions = true;
1686  }
1687 
1688  if( !has_rack_actions ) {
1689  menu.add( _( "Bike rack is empty" ) )
1690  .desc( _( "Nothing to take off or put on the rack is nearby." ) )
1691  .enable( false )
1692  .skip_locked_check();
1693  }
1694 }
void assign_activity(const activity_id &type, int moves=calendar::INDEFINITELY_LONG, int index=-1, int pos=INT_MIN, const std::string &name="")
Definition: character.cpp:8935
veh_menu_item & add(const std::string &txt)
Definition: veh_utils.cpp:256
int desc_lines_hint
Definition: veh_utils.h:71
std::vector< rackable_vehicle > find_vehicles_to_rack(int rack) const
Definition: vehicle.cpp:1528
std::vector< unrackable_vehicle > find_vehicles_to_unrack(int rack) const
Definition: vehicle.cpp:1579
vehicle_part_with_feature_range< std::string > get_any_parts(std::string feature) const
Yields a range of parts of this vehicle that each have the given feature and not removed.
Definition: vehicle.cpp:3037
veh_menu_item & enable(bool enable)
Definition: veh_utils.cpp:174
veh_menu_item & on_submit(const std::function< void()> &on_submit)
Definition: veh_utils.cpp:228
veh_menu_item & skip_locked_check(bool skip_locked_check=true)
Definition: veh_utils.cpp:186
veh_menu_item & hotkey_auto()
Definition: veh_utils.cpp:221
veh_menu_item & desc(const std::string &desc)
Definition: veh_utils.cpp:168

References _, veh_menu::add(), Character::assign_activity(), veh_menu_item::desc(), veh_menu::desc_lines_hint, veh_menu_item::enable(), find_vehicles_to_rack(), find_vehicles_to_unrack(), get_any_parts(), get_player_character(), veh_menu_item::hotkey_auto(), max(), name, veh_menu_item::on_submit(), part(), veh_menu_item::skip_locked_check(), and string_format().

◆ build_electronics_menu()

void vehicle::build_electronics_menu ( veh_menu menu)

Definition at line 285 of file vehicle_use.cpp.

286 {
287  if( has_part( "DOOR_MOTOR" ) ) {
288  menu.add( _( "Control doors and curtains" ) )
289  .hotkey( "TOGGLE_DOORS" )
290  .on_submit( [this] { control_doors(); } );
291  }
292 
293  if( camera_on || ( has_part( "CAMERA" ) && has_part( "CAMERA_CONTROL" ) ) ) {
294  menu.add( camera_on
295  ? colorize( _( "Turn off camera system" ), c_pink )
296  : _( "Turn on camera system" ) )
297  .enable( fuel_left( fuel_type_battery ) )
298  .hotkey( "TOGGLE_CAMERA" )
299  .keep_menu_open()
300  .on_submit( [&] {
301  if( camera_on )
302  {
303  add_msg( _( "Camera system disabled" ) );
304  } else
305  {
306  add_msg( _( "Camera system enabled" ) );
307  }
308  camera_on = !camera_on;
309  } );
310  }
311 
312  auto add_toggle = [this, &menu]( const std::string & name, const std::string & action,
313  const std::string & flag ) {
314  add_electronic_toggle( *this, menu, name, action, flag );
315  };
316  add_toggle( pgettext( "electronics menu option", "reactor" ),
317  "TOGGLE_REACTOR", "REACTOR" );
318  add_toggle( pgettext( "electronics menu option", "headlights" ),
319  "TOGGLE_HEADLIGHT", "CONE_LIGHT" );
320  add_toggle( pgettext( "electronics menu option", "wide angle headlights" ),
321  "TOGGLE_WIDE_HEADLIGHT", "WIDE_CONE_LIGHT" );
322  add_toggle( pgettext( "electronics menu option", "directed overhead lights" ),
323  "TOGGLE_HALF_OVERHEAD_LIGHT", "HALF_CIRCLE_LIGHT" );
324  add_toggle( pgettext( "electronics menu option", "overhead lights" ),
325  "TOGGLE_OVERHEAD_LIGHT", "CIRCLE_LIGHT" );
326  add_toggle( pgettext( "electronics menu option", "aisle lights" ),
327  "TOGGLE_AISLE_LIGHT", "AISLE_LIGHT" );
328  add_toggle( pgettext( "electronics menu option", "dome lights" ),
329  "TOGGLE_DOME_LIGHT", "DOME_LIGHT" );
330  add_toggle( pgettext( "electronics menu option", "atomic lights" ),
331  "TOGGLE_ATOMIC_LIGHT", "ATOMIC_LIGHT" );
332  add_toggle( pgettext( "electronics menu option", "stereo" ),
333  "TOGGLE_STEREO", "STEREO" );
334  add_toggle( pgettext( "electronics menu option", "chimes" ),
335  "TOGGLE_CHIMES", "CHIMES" );
336  add_toggle( pgettext( "electronics menu option", "fridge" ),
337  "TOGGLE_FRIDGE", "FRIDGE" );
338  add_toggle( pgettext( "electronics menu option", "freezer" ),
339  "TOGGLE_FREEZER", "FREEZER" );
340  add_toggle( pgettext( "electronics menu option", "arcade" ),
341  "TOGGLE_ARCADE", "ARCADE" );
342  add_toggle( pgettext( "electronics menu option", "space heater" ),
343  "TOGGLE_SPACE_HEATER", "SPACE_HEATER" );
344  add_toggle( pgettext( "electronics menu option", "heated tank" ),
345  "TOGGLE_HEATED_TANK", "HEATED_TANK" );
346  add_toggle( pgettext( "electronics menu option", "cooler" ),
347  "TOGGLE_COOLER", "COOLER" );
348  add_toggle( pgettext( "electronics menu option", "recharger" ),
349  "TOGGLE_RECHARGER", "RECHARGE" );
350  add_toggle( pgettext( "electronics menu option", "plow" ),
351  "TOGGLE_PLOW", "PLOW" );
352  add_toggle( pgettext( "electronics menu option", "reaper" ),
353  "TOGGLE_REAPER", "REAPER" );
354  add_toggle( pgettext( "electronics menu option", "planter" ),
355  "TOGGLE_PLANTER", "PLANTER" );
356  add_toggle( pgettext( "electronics menu option", "rockwheel" ),
357  "TOGGLE_PLOW", "ROCKWHEEL" );
358  add_toggle( pgettext( "electronics menu option", "roadheader" ),
359  "TOGGLE_PLOW", "ROADHEAD" );
360  add_toggle( pgettext( "electronics menu option", "scoop" ),
361  "TOGGLE_SCOOP", "SCOOP" );
362  add_toggle( pgettext( "electronics menu option", "water purifier" ),
363  "TOGGLE_WATER_PURIFIER", "WATER_PURIFIER" );
364  add_toggle( pgettext( "electronics menu option", "smart controller" ),
365  "TOGGLE_SMART_ENGINE_CONTROLLER", "SMART_ENGINE_CONTROLLER" );
366 
367  for( const vpart_reference &arc_vp : get_any_parts( "ARCADE" ) ) {
368  if( arc_vp.part().enabled ) {
369  item *arc_itm = &arc_vp.part().base;
370 
371  menu.add( _( "Play arcade machine" ) )
372  .hotkey( "ARCADE" )
373  .enable( !!arc_itm )
374  .on_submit( [arc_itm] { iuse::portable_game( &get_avatar(), arc_itm, tripoint_zero ); } );
375  break;
376  }
377  }
378 }
avatar & get_avatar()
Definition: game.cpp:13817
bool camera_on
Definition: vehicle.h:2359
bool has_part(const std::string &flag, bool enabled=false) const
Check if vehicle has at least one unbroken part with specified flag.
Definition: vehicle.cpp:2827
void control_doors()
std::string colorize(const std::string &text, const nc_color &color)
Definition: color.cpp:742
#define c_pink
Definition: color.h:29
@ action
Definition: dialogue.h:43
std::optional< int > portable_game(Character *, item *, const tripoint &)
Definition: iuse.cpp:4023
veh_menu_item & hotkey(char hotkey_char)
Definition: veh_utils.cpp:207
veh_menu_item & keep_menu_open(bool keep_menu_open=true)
Definition: veh_utils.cpp:234
static void add_electronic_toggle(vehicle &veh, veh_menu &menu, const std::string &name, const std::string &action, const std::string &flag)

References _, action, veh_menu::add(), add_electronic_toggle(), add_msg(), c_pink, camera_on, colorize(), control_doors(), veh_menu_item::enable(), fuel_left(), fuel_type_battery, get_any_parts(), get_avatar(), has_part(), veh_menu_item::hotkey(), veh_menu_item::keep_menu_open(), name, veh_menu_item::on_submit(), pgettext, iuse::portable_game(), and tripoint_zero.

Referenced by build_interact_menu().

◆ build_interact_menu()

void vehicle::build_interact_menu ( veh_menu menu,
const tripoint p,
bool  with_pickup 
)
Mechanics speeds up vehicle hotwiring

Definition at line 1822 of file vehicle_use.cpp.

1823 {
1824  const optional_vpart_position ovp = get_map().veh_at( p );
1825  if( !ovp ) {
1826  debugmsg( "vehicle::build_interact_menu couldn't find vehicle at %s", p.to_string() );
1827  return;
1828  }
1829  const vpart_position vp = *ovp;
1830  const tripoint vppos = vp.pos();
1831 
1832  std::vector<vehicle_part *> vp_parts = get_parts_at( vppos, "", part_status_flag::working );
1833 
1834  // @returns true if pos contains available part with a flag
1835  const auto has_part_here = [vp_parts]( const std::string & flag ) {
1836  return std::any_of( vp_parts.begin(), vp_parts.end(), [flag]( const vehicle_part * vp_part ) {
1837  return vp_part->info().has_flag( flag );
1838  } );
1839  };
1840 
1841  const bool remote = g->remoteveh() == this;
1842  const bool has_electronic_controls = remote
1843  ? has_part( "CTRL_ELECTRONIC" ) || has_part( "REMOTE_CONTROLS" )
1844  : has_part_here( "CTRL_ELECTRONIC" );
1845  const bool controls_here = has_part_here( "CONTROLS" );
1846  const bool player_is_driving = get_player_character().controlling_vehicle;
1847  const bool player_inside = get_map().veh_at( get_player_character().pos() ) ?
1848  &get_map().veh_at( get_player_character().pos() )->vehicle() == this :
1849  false;
1850  bool power_linked = false;
1851  bool item_linked = false;
1852  bool tow_linked = false;
1853  for( vehicle_part *vp_part : vp_parts ) {
1854  power_linked = power_linked || vp_part->info().has_flag( VPFLAG_POWER_TRANSFER );
1855  item_linked = item_linked || vp_part->has_flag( vp_flag::linked_flag );
1856  tow_linked = tow_linked || vp_part->info().has_flag( "TOW_CABLE" );
1857  }
1858 
1859  if( !is_appliance() ) {
1860  menu.add( _( "Examine vehicle" ) )
1861  .skip_theft_check()
1863  .hotkey( "EXAMINE_VEHICLE" )
1864  .on_submit( [this, vp] {
1865  const vpart_position non_fake( *this, get_non_fake_part( vp.part_index() ) );
1866  const point start_pos = non_fake.mount().rotate( 2 );
1867  g->exam_vehicle( *this, start_pos );
1868  } );
1869 
1870  menu.add( tracking_on ? _( "Forget vehicle position" ) : _( "Remember vehicle position" ) )
1871  .skip_theft_check()
1873  .keep_menu_open()
1874  .hotkey( "TOGGLE_TRACKING" )
1875  .on_submit( [this] { toggle_tracking(); } );
1876  }
1877 
1878  if( is_locked && controls_here ) {
1879  if( player_inside ) {
1880  menu.add( _( "Hotwire" ) )
1882  .desc( _( "Attempt to hotwire the car using a screwdriver." ) )
1883  .skip_locked_check()
1884  .hotkey( "HOTWIRE" )
1885  .on_submit( [this] {
1886  ///\EFFECT_MECHANICS speeds up vehicle hotwiring
1887  const float skill = std::max( 1.0f, get_player_character().get_skill_level( skill_mechanics ) );
1888  const int moves = to_moves<int>( 6000_seconds / skill );
1889  const tripoint target = global_square_location().raw() + coord_translate( parts[0].mount );
1890  const hotwire_car_activity_actor hotwire_act( moves, target );
1891  get_player_character().assign_activity( hotwire_act );
1892  } );
1893  }
1894 
1895  if( !is_alarm_on && has_security_working() ) {
1896  menu.add( _( "Trigger the alarm" ) )
1897  .desc( _( "Trigger the alarm to make noise." ) )
1898  .skip_locked_check()
1899  .hotkey( "TOGGLE_ALARM" )
1900  .on_submit( [this] {
1901  is_alarm_on = true;
1902  add_msg( _( "You trigger the alarm" ) );
1903  } );
1904  }
1905  }
1906 
1907  if( is_alarm_on && controls_here && !is_moving() && player_inside ) {
1908  menu.add( _( "Try to smash alarm" ) )
1909  .skip_locked_check()
1910  .hotkey( "TOGGLE_ALARM" )
1911  .on_submit( [this] { smash_security_system(); } );
1912  }
1913 
1914  if( remote ) {
1915  menu.add( _( "Stop controlling" ) )
1916  .hotkey( "RELEASE_CONTROLS" )
1917  .skip_theft_check()
1918  .on_submit( [] {
1920  g->setremoteveh( nullptr );
1921  add_msg( _( "You stop controlling the vehicle." ) );
1922  } );
1923  } else {
1924  if( has_part( "ENGINE" ) ) {
1925  if( ( controls_here && player_is_driving ) || ( remote && engine_on ) ) {
1926  menu.add( _( "Stop driving" ) )
1927  .hotkey( "TOGGLE_ENGINE" )
1928  .skip_theft_check()
1929  .on_submit( [this] {
1931  {
1932  add_msg( _( "You turn the engine off and let go of the controls." ) );
1933  } else
1934  {
1935  add_msg( _( "You let go of the controls." ) );
1936  }
1938  stop_engines();
1940  g->setremoteveh( nullptr );
1941  } );
1942  } else if( controls_here && has_engine_type_not( fuel_type_muscle, true ) ) {
1943  menu.add( engine_on ? _( "Turn off the engine" ) : _( "Turn on the engine" ) )
1944  .hotkey( "TOGGLE_ENGINE" )
1945  .skip_theft_check()
1946  .on_submit( [this] {
1947  if( engine_on )
1948  {
1950  add_msg( _( "You turn the engine off." ) );
1951  stop_engines();
1952  } else
1953  {
1954  start_engines();
1955  }
1956  } );
1957  }
1958  }
1959 
1960  if( player_is_driving ) {
1961  menu.add( _( "Let go of controls" ) )
1962  .hotkey( "RELEASE_CONTROLS" )
1963  .skip_locked_check() // in case player somehow controls locked vehicle
1964  .skip_theft_check()
1965  .on_submit( [] {
1967  add_msg( _( "You let go of the controls." ) );
1968  } );
1969 
1970  menu.add( _( "Pull handbrake" ) )
1971  .hotkey( "PULL_HANDBRAKE" )
1972  .on_submit( [] { handbrake(); } );
1973  }
1974 
1975  const bool has_engine_or_fuel_controls = ( engines.size() > 1 ) ||
1976  std::any_of( engines.begin(), engines.end(), [&]( int engine_idx ) {
1977  return parts[engine_idx].info().engine_info->fuel_opts.size() > 1;
1978  } );
1979 
1980  if( controls_here && has_engine_or_fuel_controls ) {
1981  menu.add( _( "Control individual engines" ) )
1982  .hotkey( "CONTROL_ENGINES" )
1983  .on_submit( [this] { control_engines(); } );
1984  }
1985  }
1986 
1987  if( controls_here && has_part( "AUTOPILOT" ) && has_electronic_controls ) {
1988  menu.add( _( "Control autopilot" ) )
1989  .hotkey( "CONTROL_AUTOPILOT" )
1990  .on_submit( [this] { toggle_autopilot(); } );
1991  }
1992 
1993  if( is_appliance() || vp.avail_part_with_feature( "CTRL_ELECTRONIC" ) ) {
1994  build_electronics_menu( menu );
1995  }
1996 
1997  if( has_electronic_controls && has_part( "SMART_ENGINE_CONTROLLER" ) ) {
1998  menu.add( _( "Smart controller settings" ) )
1999  .hotkey( "CONTROL_SMART_ENGINE" )
2000  .on_submit( [this] {
2001  if( !smart_controller_cfg )
2002  {
2004  }
2005 
2008  smart_controller_cfg -> battery_lo,
2009  smart_controller_cfg -> battery_hi );
2010  smart_controller_ui( cfg_view ).control();
2011  for( const vpart_reference &vp : get_avail_parts( "SMART_ENGINE_CONTROLLER" ) )
2012  {
2013  vp.part().enabled = cfg_view.enabled;
2014  }
2015  } );
2016  }
2017 
2018  const turret_data turret = turret_query( vp.pos() );
2019 
2020  if( turret.can_unload() ) {
2021  menu.add( string_format( _( "Unload %s" ), turret.name() ) )
2022  .hotkey( "UNLOAD_TURRET" )
2024  .on_submit( [this, vppos] {
2025  item_location loc = turret_query( vppos ).base();
2026  get_player_character().unload( loc );
2027  } );
2028  }
2029 
2030  if( turret.can_reload() ) {
2031  menu.add( string_format( _( "Reload %s" ), turret.name() ) )
2032  .hotkey( "RELOAD_TURRET" )
2034  .on_submit( [this, vppos] {
2035  item_location loc = turret_query( vppos ).base();
2037  if( opt )
2038  {
2039  reload_activity_actor reload_act( std::move( opt ) );
2040  get_player_character().assign_activity( reload_act );
2041  }
2042  } );
2043  }
2044 
2045  if( controls_here && has_part( "TURRET" ) ) {
2046  menu.add( _( "Set turret targeting modes" ) )
2047  .hotkey( "TURRET_TARGET_MODE" )
2048  .on_submit( [this] { turrets_set_targeting(); } );
2049 
2050  menu.add( _( "Set turret firing modes" ) )
2051  .hotkey( "TURRET_FIRE_MODE" )
2052  .on_submit( [this] { turrets_set_mode(); } );
2053 
2054  // We can also fire manual turrets with ACTION_FIRE while standing at the controls.
2055  menu.add( _( "Aim turrets manually" ) )
2056  .hotkey( "TURRET_MANUAL_AIM" )
2057  .on_submit( [this] { turrets_aim_and_fire_all_manual( true ); } );
2058 
2059  // This lets us manually override and set the target for the automatic turrets instead.
2060  menu.add( _( "Aim automatic turrets" ) )
2061  .hotkey( "TURRET_MANUAL_OVERRIDE" )
2062  .on_submit( [this] { turrets_override_automatic_aim(); } );
2063 
2064  menu.add( _( "Aim individual turret" ) )
2065  .hotkey( "TURRET_SINGLE_FIRE" )
2066  .on_submit( [this] { turrets_aim_and_fire_single(); } );
2067  }
2068 
2069  if( controls_here ) {
2070  if( has_part( "HORN" ) ) {
2071  menu.add( _( "Honk horn" ) )
2072  .skip_locked_check()
2073  .hotkey( "SOUND_HORN" )
2074  .on_submit( [this] { honk_horn(); } );
2075  }
2076  }
2077 
2078  if( power_linked ) {
2079  menu.add( _( "Disconnect power connections" ) )
2080  .enable( !item_linked && !tow_linked )
2081  .desc( string_format( !item_linked && !tow_linked ? "" : _( "Remove other cables first" ) ) )
2082  .skip_locked_check()
2083  .hotkey( "DISCONNECT_CABLES" )
2084  .on_submit( [this, vp] {
2085  unlink_cables( vp.mount(), get_player_character(), true, true, true );
2087  } );
2088  }
2089  if( item_linked || tow_linked ) {
2090  std::string menu_text = item_linked && tow_linked ? _( "Disconnect items and tow cables" ) :
2091  item_linked ? _( "Disconnect items" ) : _( "Disconnect tow cables" );
2092  menu.add( menu_text )
2094  .hotkey( "DISCONNECT_CABLES" )
2095  .on_submit( [this, vp] {
2096  unlink_cables( vp.mount(), get_player_character(), true, true, false );
2098  } );
2099  }
2100 
2101  const std::optional<vpart_reference> vp_toolstation = vp.avail_part_with_feature( "VEH_TOOLS" );
2102  // Remove attached tools that have become incompatible with workstation because of migration etc
2103  if( vp_toolstation && !vp.get_tools().empty() ) {
2104  const vpart_info vp_info = vp_toolstation->info();
2105  if( vp_info.toolkit_info ) {
2106  const std::set<itype_id> &allowed_tool_types = vp_info.toolkit_info->allowed_types;
2107 
2108  std::set<itype_id> builtin_tool_types;
2109  for( const auto &[tool_type, _] : vp_info.get_pseudo_tools() ) {
2110  builtin_tool_types.insert( tool_type );
2111  }
2112 
2113  std::vector<item> &stored_tools = vp_toolstation->part().tools;
2114  std::vector<item> tools_to_remove;
2115  // Tool is incompatible if it's not in allowed types and isn't a pseudo tool
2116  for( const item &tool_item : stored_tools ) {
2117  const itype_id &tool_type = tool_item.typeId();
2118  if( builtin_tool_types.find( tool_type ) != builtin_tool_types.end() ) {
2119  continue;
2120  }
2121  if( allowed_tool_types.find( tool_type ) == allowed_tool_types.end() ) {
2122  tools_to_remove.push_back( tool_item );
2123  }
2124  }
2125 
2126  if( !tools_to_remove.empty() ) {
2128  for( item &tool_to_remove : tools_to_remove ) {
2129  you.add_msg_if_player( _( "The %s is no longer compatible with %s and pops out." ),
2130  tool_to_remove.tname(), vp_toolstation->part().name( false ) );
2131  you.add_or_drop_with_msg( tool_to_remove );
2132  }
2133 
2134  stored_tools.erase( std::remove_if( stored_tools.begin(),
2135  stored_tools.end(),
2136  [&tools_to_remove]( const item & item_to_remove ) {
2137  return std::find_if( tools_to_remove.begin(), tools_to_remove.end(),
2138  [&item_to_remove]( const item & tools_to_remove_item ) {
2139  return tools_to_remove_item.typeId() == item_to_remove.typeId();
2140  } ) != tools_to_remove.end();
2141  } ),
2142  stored_tools.end() );
2143 
2144  invalidate_mass();
2146  }
2147  }
2148  }
2149 
2150  for( const auto&[tool_item, hk] : vp.get_tools() ) {
2151  const itype_id &tool_type = tool_item.typeId();
2152  if( !tool_type->has_use() ) {
2153  continue; // passive tool
2154  }
2155  if( hk == -1 ) {
2156  continue; // skip old passive tools
2157  }
2158  const auto &[tool_ammo, ammo_amount] = tool_ammo_available( tool_type );
2159  menu.add( string_format( _( "Use %s" ), tool_type->nname( 1 ) ) )
2160  .enable( ammo_amount >= tool_item.typeId()->charges_to_use() )
2161  .hotkey( hk )
2162  .skip_locked_check( tool_ammo.is_null() || tool_ammo->ammo->type != ammo_battery )
2163  .on_submit( [this, vppos, tool_type] { use_vehicle_tool( *this, vppos, tool_type ); } );
2164  }
2165 
2166  const std::optional<vpart_reference> vp_autoclave = vp.avail_part_with_feature( "AUTOCLAVE" );
2167  if( vp_autoclave ) {
2168  const size_t cl_idx = vp_autoclave->part_index();
2169  menu.add( vp_autoclave->part().enabled
2170  ? _( "Deactivate the autoclave" )
2171  : _( "Activate the autoclave (1.5 hours)" ) )
2172  .hotkey( "TOGGLE_AUTOCLAVE" )
2173  .on_submit( [this, cl_idx] { use_autoclave( cl_idx ); } );
2174  }
2175 
2176  const std::optional<vpart_reference> vp_washing_machine =
2177  vp.avail_part_with_feature( "WASHING_MACHINE" );
2178  if( vp_washing_machine ) {
2179  const size_t wm_idx = vp_washing_machine->part_index();
2180  menu.add( vp_washing_machine->part().enabled
2181  ? _( "Deactivate the washing machine" )
2182  : _( "Activate the washing machine (1.5 hours)" ) )
2183  .hotkey( "TOGGLE_WASHING_MACHINE" )
2184  .on_submit( [this, wm_idx] { use_washing_machine( wm_idx ); } );
2185  }
2186 
2187  const std::optional<vpart_reference> vp_dishwasher = vp.avail_part_with_feature( "DISHWASHER" );
2188  if( vp_dishwasher ) {
2189  const size_t dw_idx = vp_dishwasher->part_index();
2190  menu.add( vp_dishwasher->part().enabled
2191  ? _( "Deactivate the dishwasher" )
2192  : _( "Activate the dishwasher (1.5 hours)" ) )
2193  .hotkey( "TOGGLE_DISHWASHER" )
2194  .on_submit( [this, dw_idx] { use_dishwasher( dw_idx ); } );
2195  }
2196 
2197  const std::optional<vpart_reference> vp_cargo = vp.cargo();
2198  // Whether vehicle part (cargo) contains items, and whether map tile (ground) has items
2199  if( with_pickup && (
2200  get_map().has_items( vp.pos() ) ||
2201  ( vp_cargo && !vp_cargo->items().empty() ) ) ) {
2202  menu.add( _( "Get items" ) )
2203  .hotkey( "GET_ITEMS" )
2205  .skip_theft_check()
2206  .on_submit( [vppos] { g->pickup( vppos ); } );
2207  }
2208 
2209  const std::optional<vpart_reference> vp_curtain = vp.avail_part_with_feature( "CURTAIN" );
2210  if( vp_curtain && !vp_curtain->part().open ) {
2211  menu.add( _( "Peek through the closed curtains" ) )
2212  .hotkey( "CURTAIN_PEEK" )
2214  .on_submit( [vppos] {
2215  add_msg( _( "You carefully peek through the curtains." ) );
2216  g->peek( vppos );
2217  } );
2218  }
2219 
2220  if( vp.part_with_tool( itype_water_faucet ) ) {
2221  int vp_tank_idx = -1;
2222  item *water_item = nullptr;
2223  for( const int i : fuel_containers ) {
2224  vehicle_part &part = parts[i];
2225  if( part.ammo_current() == itype_water_clean &&
2227  vp_tank_idx = i;
2228  water_item = &part.base.only_item();
2229  break;
2230  }
2231  }
2232 
2233  if( vp_tank_idx != -1 && water_item != nullptr ) {
2234  menu.add( _( "Fill a container with water" ) )
2235  .hotkey( "FAUCET_FILL" )
2237  .on_submit( [this, vp_tank_idx] {
2238  item &vp_tank_item = parts[vp_tank_idx].base;
2239  item &water = vp_tank_item.only_item();
2240  liquid_handler::handle_liquid( water, &vp_tank_item, 1, nullptr, this, vp_tank_idx );
2241  } );
2242 
2243  menu.add( _( "Have a drink" ) )
2244  .enable( get_player_character().will_eat( *water_item ).success() )
2245  .hotkey( "FAUCET_DRINK" )
2247  .on_submit( [this, vp_tank_idx] {
2248  vehicle_part &vp_tank = parts[vp_tank_idx];
2249  // this is not "proper" use of vehicle_cursor, but should be good enough for reducing
2250  // charges and deleting the liquid on last charge drained, for more details see #61164
2251  item_location base_loc( vehicle_cursor( *this, vp_tank_idx ), &vp_tank.base );
2252  item_location water_loc( base_loc, &vp_tank.base.only_item() );
2253  const consume_activity_actor consume_act( water_loc );
2254  get_player_character().assign_activity( consume_act );
2255  } );
2256  }
2257  }
2258 
2259  if( vp.part_with_tool( itype_water_purifier ) ) {
2260  menu.add( _( "Purify water in vehicle tank" ) )
2261  .enable( fuel_left( itype_water ) &&
2263  .hotkey( "PURIFY_WATER" )
2264  .on_submit( [this] {
2265  const auto sel = []( const vehicle_part & pt )
2266  {
2267  return pt.is_tank() && pt.ammo_current() == itype_water;
2268  };
2269  std::string title = string_format( _( "Purify <color_%s>water</color> in tank" ),
2270  get_all_colors().get_name( itype_water->color ) );
2271  const std::optional<vpart_reference> vpr = veh_interact::select_part( *this, sel, title );
2272  if( !vpr )
2273  {
2274  return;
2275  }
2276  vehicle_part &tank = vpr->part();
2277  int64_t cost = static_cast<int64_t>( itype_water_purifier->charges_to_use() );
2278  if( fuel_left( itype_battery ) < tank.ammo_remaining() * cost )
2279  {
2280  //~ $1 - vehicle name, $2 - part name
2281  add_msg( m_bad, _( "Insufficient power to purify the contents of the %1$s's %2$s" ),
2282  name, tank.name() );
2283  } else
2284  {
2285  //~ $1 - vehicle name, $2 - part name
2286  add_msg( m_good, _( "You purify the contents of the %1$s's %2$s" ), name, tank.name() );
2287  discharge_battery( tank.ammo_remaining() * cost );
2288  tank.ammo_set( itype_water_clean, tank.ammo_remaining() );
2289  }
2290  } );
2291  }
2292 
2293  const std::optional<vpart_reference> vp_monster_capture =
2294  vp.avail_part_with_feature( "CAPTURE_MONSTER_VEH" );
2295  if( vp_monster_capture ) {
2296  const size_t mc_idx = vp_monster_capture->part_index();
2297  menu.add( _( "Capture or release a creature" ) )
2298  .hotkey( "USE_CAPTURE_MONSTER_VEH" )
2299  .on_submit( [this, mc_idx, vppos] { use_monster_capture( mc_idx, vppos ); } );
2300  }
2301 
2302  const std::optional<vpart_reference> vp_bike_rack = vp.avail_part_with_feature( "BIKE_RACK_VEH" );
2303  if( vp_bike_rack ) {
2304  build_bike_rack_menu( menu, vp_bike_rack->part_index() );
2305  }
2306 
2307  const std::optional<vpart_reference> vp_harness = vp.avail_part_with_feature( "ANIMAL_CTRL" );
2308  if( vp_harness ) {
2309  const size_t hn_idx = vp_harness->part_index();
2310  menu.add( _( "Harness an animal" ) )
2311  .hotkey( "USE_ANIMAL_CTRL" )
2312  .on_submit( [this, hn_idx, vppos] { use_harness( hn_idx, vppos ); } );
2313  }
2314 
2315  if( vp.avail_part_with_feature( "PLANTER" ) ) {
2316  menu.add( _( "Reload seed drill with seeds" ) )
2317  .hotkey( "USE_PLANTER" )
2318  .on_submit( [this, vppos] { reload_seeds( vppos ); } );
2319  }
2320 
2321  const std::optional<vpart_reference> vp_workbench = vp.avail_part_with_feature( "WORKBENCH" );
2322  if( vp_workbench ) {
2323  const size_t wb_idx = vp_workbench->part_index();
2324  menu.add( string_format( _( "Craft at the %s" ), vp_workbench->part().name() ) )
2325  .hotkey( "USE_WORKBENCH" )
2327  .on_submit( [this, wb_idx, vppos] {
2328  const vpart_reference vp_workbench( *this, wb_idx );
2329  iexamine::workbench_internal( get_player_character(), vppos, vp_workbench );
2330  } );
2331  }
2332 
2333  if( vp_toolstation && vp_toolstation->info().toolkit_info ) {
2334  const size_t vp_idx = vp_toolstation->part_index();
2335  const std::string vp_name = vp_toolstation->part().name( /* with_prefix = */ false );
2336 
2337  menu.add( string_format( _( "Attach a tool to %s" ), vp_name ) )
2338  .skip_locked_check( true )
2339  .on_submit( [this, vp_idx, vp_name] {
2341  vehicle_part &vp = part( vp_idx );
2342  std::set<itype_id> allowed_types = vp.info().toolkit_info->allowed_types;
2343  for( const std::pair<const item, int> &pair : prepare_tools( vp ) )
2344  {
2345  allowed_types.erase( pair.first.typeId() ); // one tool of each kind max
2346  }
2347 
2348  item_location loc = game_menus::inv::veh_tool_attach( you, vp_name, allowed_types );
2349 
2350  if( !loc )
2351  {
2352  you.add_msg_if_player( _( "Never mind." ) );
2353  return;
2354  }
2355 
2356  item &obj = *loc.get_item();
2357  you.add_msg_if_player( _( "You attach %s to %s." ), obj.tname(), vp_name );
2358 
2359  vp.tools.emplace_back( obj );
2360  loc.remove_item();
2361  invalidate_mass();
2363  } );
2364 
2365  const bool detach_ok = !get_tools( part( vp_idx ) ).empty();
2366  menu.add( string_format( _( "Detach a tool from %s" ), vp_name ) )
2367  .enable( detach_ok )
2368  .desc( string_format( detach_ok ? "" : _( "There are no tools attached to %s" ), vp_name ) )
2369  .skip_locked_check( true )
2370  .on_submit( [this, vp_idx, vp_name] {
2371  veh_menu detach_menu( this, string_format( _( "Detach a tool from %s" ), vp_name ) );
2372 
2373  vehicle_part &vp_tools = part( vp_idx );
2374  for( item &i : get_tools( vp_tools ) )
2375  {
2376  detach_menu.add( i.display_name() )
2377  .skip_locked_check( true )
2378  .skip_theft_check( true )
2379  .on_submit( [this, &i, &vp_tools, vp_name]() {
2381  std::vector<item> &tools = get_tools( vp_tools );
2382  const auto it_to_remove = std::find_if( tools.begin(), tools.end(),
2383  [&i]( const item & it ) {
2384  return &it == &i;
2385  } );
2386  get_player_character().add_msg_if_player( _( "You detach %s from %s." ),
2387  i.tname(), vp_name );
2388  you.add_or_drop_with_msg( *it_to_remove );
2389  tools.erase( it_to_remove );
2390  invalidate_mass();
2392  } );
2393 
2394  }
2395  detach_menu.query();
2396  } );
2397  }
2398 
2399  if( is_foldable() && !remote ) {
2400  menu.add( string_format( _( "Fold %s" ), name ) )
2401  .hotkey( "FOLD_VEHICLE" )
2402  .on_submit( [this] {
2403  vehicle_folding_activity_actor folding_act( *this );
2404  get_avatar().assign_activity( folding_act );
2405  } );
2406  }
2407 
2408  const std::optional<vpart_reference> vp_lockable_door =
2409  vp.avail_part_with_feature( "LOCKABLE_DOOR" );
2410  const std::optional<vpart_reference> vp_door_lock = vp.avail_part_with_feature( "DOOR_LOCKING" );
2411  if( vp_lockable_door && vp_door_lock && !vp_lockable_door->part().open ) {
2412  if( player_inside && !vp_lockable_door->part().locked ) {
2413  menu.add( string_format( _( "Lock %s" ), vp_lockable_door->part().name() ) )
2414  .hotkey( "LOCK_DOOR" )
2415  .on_submit( [p] {
2417  } );
2418  } else if( player_inside && vp_lockable_door->part().locked ) {
2419  menu.add( string_format( _( "Unlock %s" ), vp_lockable_door->part().name() ) )
2420  .hotkey( "UNLOCK_DOOR" )
2421  .on_submit( [p] {
2423  } );
2424  } else if( vp_lockable_door->part().locked ) {
2425  menu.add( string_format( _( "Check the lock on %s" ), vp_lockable_door->part().name() ) )
2426  .hotkey( "LOCKPICK" )
2427  .on_submit( [p] {
2429  } );
2430  }
2431  }
2432 }
bool controlling_vehicle
Is currently in control of a vehicle.
Definition: character.h:559
virtual item::reload_option select_ammo(const item_location &base, bool prompt=false, bool empty=true)=0
Select suitable ammo with which to reload the item.
void pause()
bool unload(item_location &loc, bool bypass_activity=false, const item_location &new_container=item_location::nowhere)
Unload item.
ret_val< edible_rating > will_eat(const item &food, bool interactive=false) const
Same as can_eat, but takes consequences into account.
const inventory & crafting_inventory(bool clear_path) const
Definition: crafting.cpp:629
void add_msg_if_player(const std::string &msg) const override
Definition: character.cpp:856
bool add_or_drop_with_msg(item &it, bool unloading=false, const item *avoid=nullptr, const item *original_inventory_item=nullptr)
So far only called by unload() from game.cpp @avoid - do not put @it into @avoid @original_inventory_...
void invalidate_crafting_inventory()
Definition: crafting.cpp:692
bool has_quality(const quality_id &qual, int level=1, int qty=1) const override
Returns true if instance has amount (or more) items of at least quality level.
A lightweight handle to an item independent of it's location Unlike a raw pointer can be (de-)seriali...
Definition: item_location.h:29
item * get_item()
Gets the selected item or nullptr.
void remove_item()
Removes the selected item from the game.
const std::map< material_id, int > & made_of() const
The ids of all the materials this is made of.
Definition: item.cpp:9146
std::string tname(unsigned int quantity=1, tname::segment_bitset const &segments=tname::default_tname) const
Return the (translated) item name.
Definition: item.cpp:6814
item & only_item()
Definition: item.cpp:15145
optional_vpart_position veh_at(const tripoint &p) const
Checks if tile is occupied by vehicle and by which part.
Definition: map.cpp:1316
Simple wrapper to forward functions that may return a std::optional to vpart_position.
bool can_reload() const
Definition: turret.cpp:212
std::string name() const
Definition: turret.cpp:74
item_location base()
Get base item location.
Definition: turret.cpp:79
bool can_unload() const
Definition: turret.cpp:228
static std::optional< vpart_reference > select_part(const vehicle &veh, const part_selector &sel, const std::string &title=std::string())
Prompt for a part matching the selector function.
bool has_enabled_smart_controller
Definition: vehicle.h:2227
void use_dishwasher(int p)
std::pair< const itype_id &, int > tool_ammo_available(const itype_id &tool_type) const
if tool is not an itype with tool != nullptr this returns { itype::NULL_ID(), 0 } pair
void turrets_override_automatic_aim()
Set target for automatic turrets using the aiming UI.
Definition: turret.cpp:371
void build_electronics_menu(veh_menu &menu)
void build_bike_rack_menu(veh_menu &menu, int part)
void turrets_set_targeting()
Set targeting mode for specific turrets.
Definition: turret.cpp:453
void turrets_set_mode()
Set firing mode for specific turrets.
Definition: turret.cpp:509
void use_autoclave(int p)
std::vector< vehicle_part * > get_parts_at(const tripoint &pos, const std::string &flag, part_status_flag condition)
Get all enabled, available, unbroken vehicle parts at specified position.
Definition: vehicle.cpp:2855
bool has_engine_type_not(const itype_id &ft, bool enabled) const
Definition: vehicle.cpp:967
int get_non_fake_part(int part_num) const
Definition: vehicle.cpp:8108
void use_monster_capture(int part, const tripoint &pos)
bool is_locked
Definition: vehicle.h:2356
void honk_horn() const
void start_engines(bool take_control=false, bool autodrive=false)
void smash_security_system()
std::vector< item > & get_tools(vehicle_part &vp)
Definition: vehicle.cpp:5927
static bool use_vehicle_tool(vehicle &veh, const tripoint &vp_pos, const itype_id &tool_type, bool no_invoke=false)
int discharge_battery(int amount, bool apply_loss=true)
Discharges batteries in connected vehicles/appliances.
Definition: vehicle.cpp:5564
void use_harness(int part, const tripoint &pos)
std::map< item, int > prepare_tools(const vehicle_part &vp) const
Definition: vehicle.cpp:5937
void disable_smart_controller_if_needed()
Definition: vehicle.cpp:5796
bool is_appliance() const
Definition: vehicle.cpp:1445
void turrets_aim_and_fire_single()
Select a single ready turret, aim it using the aiming UI and fire.
Definition: turret.cpp:325
bool tracking_on
Definition: vehicle.h:2354
void stop_engines()
std::optional< smart_controller_config > smart_controller_cfg
Definition: vehicle.h:2226
point coord_translate(const point &p) const
Definition: vehicle.cpp:3301
void toggle_autopilot()
void use_washing_machine(int p)
bool is_foldable() const
Definition: vehicle.cpp:7594
std::vector< int > fuel_containers
Definition: vehicle.h:2191
bool is_moving() const
Definition: vehicle.cpp:3728
bool turrets_aim_and_fire_all_manual(bool show_msg=false)
Definition: turret.cpp:355
void control_engines()
void reload_seeds(const tripoint &pos)
void toggle_tracking()
void unlink_cables(const point &mount, Character &remover, bool unlink_items=false, bool unlink_tow_cables=false, bool unlink_power_cords=false)
Disconnect cables attached to the specified mount point.
Definition: vehicle.cpp:7025
std::set< std::pair< itype_id, int > > get_pseudo_tools() const
Definition: veh_type.cpp:1131
std::optional< vpslot_toolkit > toolkit_info
Definition: veh_type.h:295
Reference to a position (a point) of the vehicle.
std::map< item, int > get_tools() const
Definition: vehicle.cpp:2645
point mount() const
Returns the mount point: the point in the vehicles own coordinate system.
Definition: vehicle.cpp:7808
std::optional< vpart_reference > part_with_tool(const itype_id &tool_type) const
Definition: vehicle.cpp:2627
std::optional< vpart_reference > cargo() const
Definition: vehicle.cpp:2660
size_t part_index() const
tripoint pos() const
Definition: vehicle.cpp:7817
std::optional< vpart_reference > avail_part_with_feature(const std::string &f) const
Definition: vehicle.cpp:2685
color_manager & get_all_colors()
Definition: color.cpp:43
coords::coord_point< tripoint, coords::origin::reality_bubble, coords::ms > tripoint_bub_ms
Definition: coordinates.h:716
@ m_good
Definition: enums.h:347
bool unlock_door(map &m, Creature &who, const tripoint_bub_ms &lockp)
Unlocks a door at "lockp" as "who.".
Definition: gates.cpp:409
bool lock_door(map &m, Creature &who, const tripoint_bub_ms &lockp)
Locks a door at "lockp" as "who.".
Definition: gates.cpp:356
item_location veh_tool_attach(Character &you, const std::string &vp_name, const std::set< itype_id > &allowed_types)
Choosing an item to attach to a vehicle tool station.
void locked_object(Character &you, const tripoint &examp)
Checks whether PC has a crowbar then calls iuse.crowbar.
Definition: iexamine.cpp:1826
void workbench_internal(Character &you, const tripoint &examp, const std::optional< vpart_reference > &part)
Definition: iexamine.cpp:7170
bool handle_liquid(item &liquid, const item *const source, const int radius, const tripoint *const source_pos, const vehicle *const source_veh, const int part_num, const monster *const source_mon)
This may start a player activity if either source_pos or source_veh is not null.
@ title
Definition: music.h:14
bool has_use() const
Definition: itype.cpp:159
int charges_to_use() const
Definition: itype.cpp:139
std::string nname(unsigned int quantity) const
Definition: itype.cpp:95
nc_color color
Definition: itype.h:1420
point rotate(int turns, const point &dim={ 1, 1 }) const
Rotate point clockwise.
Definition: point.cpp:24
Configurable settings for the Smart Controller.
std::string to_string() const
Definition: point.cpp:79
veh_menu_item & skip_theft_check(bool skip_theft_check=true)
Definition: veh_utils.cpp:180
std::vector< item > tools
Definition: vehicle.h:543
int ammo_set(const itype_id &ammo, int qty=-1)
Set fuel, charges or ammunition for this part removing any existing ammo.
static const itype_id itype_water_clean("water_clean")
static const ammotype ammo_battery("battery")
static const itype_id itype_water_purifier("water_purifier")
static const skill_id skill_mechanics("mechanics")
static const itype_id itype_water_faucet("water_faucet")
static const quality_id qual_SCREW("SCREW")
static const itype_id itype_battery("battery")
static const itype_id itype_water("water")
static const itype_id fuel_type_muscle("muscle")
void handbrake()

References _, veh_menu::add(), add_msg(), Character::add_msg_if_player(), Character::add_or_drop_with_msg(), Character::assign_activity(), vpart_position::avail_part_with_feature(), turret_data::base(), build_electronics_menu(), turret_data::can_reload(), turret_data::can_unload(), smart_controller_ui::control(), control_engines(), Character::controlling_vehicle, coord_translate(), Character::crafting_inventory(), debugmsg, veh_menu_item::desc(), disable_smart_controller_if_needed(), smart_controller_settings::enabled, engine_on, engines, fuel_type_muscle, g, get_avail_parts(), get_map(), get_non_fake_part(), get_parts_at(), get_player_character(), vpart_info::get_pseudo_tools(), vpart_position::get_tools(), global_square_location(), handbrake(), has_enabled_smart_controller, has_engine_type_not(), has_part(), inventory::has_quality(), has_security_working(), honk_horn(), veh_menu_item::hotkey(), invalidate_mass(), is_alarm_on, is_appliance(), is_locked, is_moving(), veh_menu_item::keep_menu_open(), linked_flag, max(), vpart_position::mount(), turret_data::name(), veh_menu_item::on_submit(), vpart_position::part_index(), parts, Character::pause(), pos, vpart_position::pos(), qual_SCREW, coords::coord_point_mut< Point, Subpoint, InBounds >::raw(), point::rotate(), Character::select_ammo(), skill_mechanics, veh_menu_item::skip_locked_check(), veh_menu_item::skip_theft_check(), smart_controller_cfg, smash_security_system(), start_engines(), stop_engines(), string_format(), tripoint::to_string(), toggle_autopilot(), toggle_tracking(), vpart_info::toolkit_info, tracking_on, turret_query(), turrets_aim_and_fire_all_manual(), turrets_aim_and_fire_single(), turrets_override_automatic_aim(), turrets_set_mode(), turrets_set_targeting(), unlink_cables(), Character::unload(), map::veh_at(), VPFLAG_POWER_TRANSFER, and working.

Referenced by interact_with(), and veh_app_interact::populate_app_actions().

◆ calc_mass_center()

void vehicle::calc_mass_center ( bool  precalc) const
private

Definition at line 7997 of file vehicle.cpp.

7998 {
8001  units::mass m_total = 0_gram;
8002  for( const vpart_reference &vp : get_all_parts() ) {
8003  const size_t i = vp.part_index();
8004  if( vp.part().removed || vp.part().is_fake ) {
8005  continue;
8006  }
8007 
8008  units::mass m_part = 0_gram;
8009  units::mass m_part_items = 0_gram;
8010  m_part += vp.part().base.weight();
8011  for( const item &j : get_items( vp.part() ) ) {
8012  m_part_items += j.weight();
8013  }
8014  for( const item &j : get_tools( vp.part() ) ) {
8015  m_part_items += j.weight();
8016  }
8017  if( vp.part().info().cargo_weight_modifier != 100 ) {
8018  m_part_items *= static_cast<float>( vp.part().info().cargo_weight_modifier ) / 100.0f;
8019  }
8020  m_part += m_part_items;
8021 
8022  if( vp.has_feature( VPFLAG_BOARDABLE ) ) {
8023  const Character *p = get_passenger( i );
8024  const monster *z = get_monster( i );
8025  // Sometimes flag is wrongly set, don't crash!
8026  m_part += p != nullptr ? p->get_weight() : 0_gram;
8027  m_part += z != nullptr ? z->get_weight() : 0_gram;
8028  }
8029  if( use_precalc ) {
8030  xf += vp.part().precalc[0].x * m_part;
8031  yf += vp.part().precalc[0].y * m_part;
8032  } else {
8033  xf += vp.mount().x * m_part;
8034  yf += vp.mount().y * m_part;
8035  }
8036 
8037  m_total += m_part;
8038  }
8039 
8040  mass_cache = m_total;
8041  mass_dirty = false;
8042 
8043  const float x = xf / mass_cache;
8044  const float y = yf / mass_cache;
8045  if( use_precalc ) {
8048  mass_center_precalc_dirty = false;
8049  } else {
8053  }
8054 }
units::mass get_weight() const override
Returns body weight plus weight of inventory and worn/wielded items.
Definition: character.cpp:3889
units::mass get_weight() const override
Definition: monster.cpp:3508
point mass_center_precalc
Definition: vehicle.h:2242
units::mass mass_cache
Definition: vehicle.h:2234
bool mass_center_precalc_dirty
Definition: vehicle.h:2322
bool mass_dirty
Definition: vehicle.h:2321
point mass_center_no_precalc
Definition: vehicle.h:2243
bool mass_center_no_precalc_dirty
Definition: vehicle.h:2323
double round(std::vector< double > const &params)

References get_all_parts(), get_items(), get_monster(), get_passenger(), get_tools(), Character::get_weight(), monster::get_weight(), mass_cache, mass_center_no_precalc, mass_center_no_precalc_dirty, mass_center_precalc, mass_center_precalc_dirty, mass_dirty, vpart_position::mount(), vpart_position::part_index(), round(), VPFLAG_BOARDABLE, point::x, and point::y.

Referenced by local_center_of_mass(), rotated_center_of_mass(), and total_mass().

◆ can_close()

bool vehicle::can_close ( int  part_index,
Character who 
)

Definition at line 1252 of file vehicle_use.cpp.

1253 {
1254  creature_tracker &creatures = get_creature_tracker();
1255  part_index = get_non_fake_part( part_index );
1256  std::vector<std::vector<int>> openable_parts = find_lines_of_parts( part_index, "OPENABLE" );
1257  if( openable_parts.empty() ) {
1258  std::vector<int> base_element;
1259  base_element.push_back( part_index );
1260  openable_parts.emplace_back( base_element );
1261  }
1262  for( const std::vector<int> &vec : openable_parts ) {
1263  for( int partID : vec ) {
1264  // Check the part for collisions, then if there's a fake part present check that too.
1265  while( partID >= 0 ) {
1266  const Creature *const mon = creatures.creature_at( global_part_pos3( parts[partID] ) );
1267  if( mon ) {
1268  if( mon->is_avatar() ) {
1269  who.add_msg_if_player( m_info, _( "There's some buffoon in the way!" ) );
1270  } else if( mon->is_monster() ) {
1271  // TODO: Houseflies, mosquitoes, etc shouldn't count
1272  who.add_msg_if_player( m_info, _( "The %s is in the way!" ), mon->get_name() );
1273  } else {
1274  who.add_msg_if_player( m_info, _( "%s is in the way!" ), mon->disp_name() );
1275  }
1276  return false;
1277  }
1278  if( parts[partID].has_fake && parts[parts[partID].fake_part_at].is_active_fake ) {
1279  partID = parts[partID].fake_part_at;
1280  } else {
1281  partID = -1;
1282  }
1283  }
1284  }
1285  }
1286  return true;
1287 }
virtual bool is_monster() const
Definition: creature.h:271
virtual std::string disp_name(bool possessive=false, bool capitalize_first=false) const =0
virtual std::string get_name() const =0
virtual bool is_avatar() const
Definition: creature.h:265
T * creature_at(const tripoint &p, bool allow_hallucination=false)
Returns the Creature at the given location.
std::vector< std::vector< int > > find_lines_of_parts(int part, const std::string &flag) const
Returns all parts in the vehicle that have the specified flag in their vpinfo and are on the same X-a...
Definition: vehicle.cpp:3120
creature_tracker & get_creature_tracker()
Definition: game.cpp:13827

References _, Character::add_msg_if_player(), creature_tracker::creature_at(), Creature::disp_name(), find_lines_of_parts(), get_creature_tracker(), Creature::get_name(), get_non_fake_part(), global_part_pos3(), Creature::is_avatar(), Creature::is_monster(), m_info, and parts.

Referenced by doors::close_door(), and control_doors().

◆ can_control_in_air()

bool vehicle::can_control_in_air ( const Character pc) const

Definition at line 4467 of file vehicle.cpp.

4468 {
4469  for( const int index : control_req_parts ) {
4470  for( const proficiency_id prof : parts[index].info().control_air.proficiencies ) {
4471  if( !pc.has_proficiency( prof ) ) {
4472  return false;
4473  }
4474  }
4475  for( const std::pair<string_id<Skill>, int> &skill : parts[index].info().control_air.skills ) {
4476  if( pc.get_skill_level( skill.first ) < skill.second ) {
4477  return false;
4478  }
4479  }
4480  }
4481  return true;
4482 }
bool has_proficiency(const proficiency_id &prof) const
float get_skill_level(const skill_id &ident) const
Definition: character.cpp:3428
std::vector< int > control_req_parts
Definition: vehicle.h:2198

References control_req_parts, Character::get_skill_level(), Character::has_proficiency(), and parts.

Referenced by pldrive().

◆ can_control_on_land()

bool vehicle::can_control_on_land ( const Character pc) const

Definition at line 4484 of file vehicle.cpp.

4485 {
4486  for( const int index : control_req_parts ) {
4487  for( const proficiency_id prof : parts[index].info().control_land.proficiencies ) {
4488  if( !pc.has_proficiency( prof ) ) {
4489  return false;
4490  }
4491  }
4492  for( const std::pair<string_id<Skill>, int> &skill : parts[index].info().control_land.skills ) {
4493  if( pc.get_skill_level( skill.first ) < skill.second ) {
4494  return false;
4495  }
4496  }
4497  }
4498  return true;
4499 }

References control_req_parts, Character::get_skill_level(), Character::has_proficiency(), and parts.

Referenced by pldrive().

◆ can_enable()

bool vehicle::can_enable ( const vehicle_part pt,
bool  alert = false 
) const

Test if part can be enabled (unbroken, sufficient fuel etc), optionally displaying failures to user.

Definition at line 662 of file vehicle_part.cpp.

663 {
664  if( std::none_of( parts.begin(), parts.end(), [&pt]( const vehicle_part & e ) {
665  return &e == &pt;
666 } ) || pt.removed ) {
667  debugmsg( "Cannot enable removed or non-existent part" );
668  }
669 
670  if( pt.is_broken() ) {
671  return false;
672  }
673 
674  if( pt.info().has_flag( "PLANTER" ) && !warm_enough_to_plant( get_player_character().pos() ) ) {
675  if( alert ) {
676  add_msg( m_bad, _( "It is too cold to plant anything now." ) );
677  }
678  return false;
679  }
680 
681  // TODO: check fuel for combustion engines
682 
683  if( pt.info().epower < 0_W && fuel_left( fuel_type_battery ) <= 0 ) {
684  if( alert ) {
685  add_msg( m_bad, _( "Insufficient power to enable %s" ), pt.name() );
686  }
687  return false;
688  }
689 
690  return true;
691 }
units::power epower
Electrical power, flat rate energy (per second); positive for generation, negative for consumption Fo...
Definition: veh_type.h:418
bool warm_enough_to_plant(const tripoint &pos)
Is it warm enough to plant seeds?
Definition: weather.cpp:875
bool removed
true if this part is removed.
Definition: vehicle.h:506
static const itype_id fuel_type_battery("battery")

References _, add_msg(), debugmsg, vpart_info::epower, fuel_left(), fuel_type_battery, get_player_character(), vpart_info::has_flag(), vehicle_part::info(), vehicle_part::is_broken(), m_bad, vehicle_part::name(), parts, pos, vehicle_part::removed, and warm_enough_to_plant().

◆ can_float()

bool vehicle::can_float ( ) const

can_float does the vehicle have freeboard or does it overflow with water?

Definition at line 4349 of file vehicle.cpp.

4350 {
4351  if( coeff_water_dirty ) {
4352  coeff_water_drag();
4353  }
4354  // Someday I'll deal with submarines, but now, you can only float if you have freeboard
4355  return draft_m < hull_height;
4356 }
bool coeff_water_dirty
Definition: vehicle.h:2327
double hull_height
Definition: vehicle.h:2111
double draft_m
Definition: vehicle.h:2110
double coeff_water_drag() const
coefficient of water drag in kg/m multiplied by the square of speed to calculate water drag force in ...
Definition: vehicle.cpp:4501

References coeff_water_dirty, coeff_water_drag(), draft_m, and hull_height.

Referenced by act_on_map(), overmap_ui::get_overmap_path_to(), k_traction(), map::move_vehicle(), on_move(), game::place_vehicle_nearby(), slowdown(), steering_effectiveness(), thrust(), vehicle_unfolding_activity_actor::unfold_vehicle(), map::vehicle_wheel_traction(), wait(), and wheel_state_description().

◆ can_mount()

ret_val< void > vehicle::can_mount ( const point dp,
const vpart_info vpi 
) const
Parameters
dpThe coordinate to mount at (in vehicle mount point coords)
vpiThe part type to check
Returns
true if the part can be mounted at specified position.

Definition at line 1181 of file vehicle.cpp.

1182 {
1183  const std::vector<int> parts_in_square = parts_at_relative( dp,
1184  /* use_cache = */ false, /* include_fake = */ false );
1185 
1186  if( parts_in_square.empty() ) {
1187  // First part in an empty square MUST be a structural part or be an appliance
1188  if( vpi.location != part_location_structure ) {
1189  return ret_val<void>::make_failure( _( "There's no structure to support it." ) );
1190  }
1191  } else {
1192  const vpart_info &vpi_first_in_square = part( parts_in_square[0] ).info();
1193  // Only tow cables can be placed on tiles with an animal harness or protrusion
1194  if( vpi_first_in_square.has_flag( "ANIMAL_CTRL" ) ||
1195  vpi_first_in_square.has_flag( "PROTRUSION" ) ) {
1196  if( !vpi.has_flag( "TOW_CABLE" ) ) {
1197  return ret_val<void>::make_failure( _( "%s is in the way." ), vpi_first_in_square.name() );
1198  }
1199  }
1200  }
1201 
1202  for( const int elem : parts_in_square ) {
1203  const vpart_info &vpi_other = part( elem ).info();
1204  // No part type can stack with itself, except power cables
1205  if( vpi.id == vpi_other.id && !vpi.has_flag( VPFLAG_POWER_TRANSFER ) ) {
1206  return ret_val<void>::make_failure( _( "%s is already installed here." ), vpi.name() );
1207  }
1208  // Only parts with empty or different locations can be on same tile
1209  if( !vpi.location.empty() && vpi.location == vpi_other.location ) {
1210  const std::string loc = string_replace( vpi.location, "_", " " ); // slightly more user friendly
1211  //~ %1$s - already installed part name, %2$s - part location name
1212  return ret_val<void>::make_failure( _( "The installed %1$s already occupies the '%2$s' location." ),
1213  vpi_other.name(), loc );
1214  }
1215  // Until we have an interface for handling multiple components with CARGO space,
1216  // exclude them from being mounted in the same tile.
1217  if( vpi.has_flag( VPFLAG_CARGO ) && vpi_other.has_flag( VPFLAG_CARGO ) ) {
1219  _( "There can't be two cargo parts on the same tile. "
1220  "Part conflicts with existing %1$s." ), vpi_other.name() );
1221  }
1222  // Mirrors cannot be mounted on OPAQUE parts
1223  if( vpi.has_flag( "VISION" ) && !vpi.has_flag( "CAMERA" ) ) {
1224  if( vpi_other.has_flag( VPFLAG_OPAQUE ) ) {
1225  return ret_val<void>::make_failure( _( "Mirrors cannot be mounted on opaque parts." ) );
1226  }
1227  }
1228  // Opaque parts cannot be mounted on mirrors parts
1229  if( vpi.has_flag( VPFLAG_OPAQUE ) ) {
1230  if( vpi_other.has_flag( "VISION" ) && !vpi_other.has_flag( "CAMERA" ) ) {
1231  return ret_val<void>::make_failure( _( "Opaque parts cannot be mounted on mirror parts." ) );
1232  }
1233  }
1234  // Turret mounts must NOT be installed on other (modded) turret mounts
1235  if( vpi.has_flag( "TURRET_MOUNT" ) ) {
1236  if( vpi_other.has_flag( "TURRET_MOUNT" ) ) {
1237  return ret_val<void>::make_failure( _( "Only one turret mount can be installed." ) );
1238  }
1239  }
1240  }
1241 
1242  // All parts after the first must be installed on or next to an existing part
1243  // the exception is when a single tile only structural object is being repaired
1244  if( !parts.empty() ) {
1245  if( !is_structural_part_removed() &&
1246  !has_structural_part( dp ) &&
1247  !has_structural_part( dp + point_east ) &&
1248  !has_structural_part( dp + point_south ) &&
1249  !has_structural_part( dp + point_west ) &&
1250  !has_structural_part( dp + point_north ) ) {
1251  return ret_val<void>::make_failure( _( "Part needs to be adjacent to or on existing structure." ) );
1252  }
1253  }
1254 
1255  if( const std::optional<std::string> conflict = has_engine_conflict( vpi ) ) {
1256  return ret_val<void>::make_failure( _( "Engine conflict: %s." ), conflict.value() );
1257  }
1258 
1259  // Check all the flags of the part to see if they require other flags
1260  // If other flags are required check if those flags are present
1261  for( const std::string &flag : vpi.get_flags() ) {
1262  const std::string &required_flag = json_flag::get( flag ).requires_flag();
1263  if( required_flag.empty() ) {
1264  continue;
1265  }
1266  const bool flag_found = std::any_of( parts_in_square.begin(), parts_in_square.end(),
1267  [this, &required_flag]( int elem ) {
1268  return part( elem ).info().has_flag( required_flag );
1269  } );
1270  if( flag_found ) {
1271  continue;
1272  }
1273  std::set<std::string> possible_parts;
1274  for( const vpart_info &vpi_option : vehicles::parts::get_all() ) {
1275  if( vpi_option.has_flag( required_flag ) &&
1276  !vpi_option.has_flag( "NO_INSTALL_PLAYER" ) &&
1277  !vpi_option.has_flag( "NO_INSTALL_HIDDEN" ) ) {
1278  possible_parts.emplace( vpi_option.name() );
1279  }
1280  }
1281  if( possible_parts.empty() ) {
1282  return ret_val<void>::make_failure( "%s flag required but no parts provide it, this is a bug",
1283  required_flag );
1284  } else if( possible_parts.size() == 1 ) {
1285  return ret_val<void>::make_failure( _( "Part requires %s." ), *possible_parts.begin() );
1286  } else {
1287  return ret_val<void>::make_failure( _( "Part requires any of: %s." ),
1289  }
1290  }
1291 
1292  // Anything not explicitly denied is permitted
1293  return ret_val<void>::make_success();
1294 }
static ret_val make_success(T val=default_success::value)
Definition: ret_val.h:63
static ret_val make_failure(T val=default_failure::value)
Definition: ret_val.h:67
bool is_structural_part_removed() const
Returns whether or not the vehicle has a structural part queued for removal,.
Definition: vehicle.cpp:1171
bool has_structural_part(const point &dp) const
Definition: vehicle.cpp:1153
std::optional< std::string > has_engine_conflict(const vpart_info &possible_conflict) const
Definition: vehicle.cpp:978
vpart_id id
Definition: veh_type.h:242
std::string name() const
Translated name of a part.
Definition: veh_type.cpp:965
const std::vector< vpart_info > & get_all()
Definition: veh_type.cpp:960
std::string string_replace(std::string text, const std::string &before, const std::string &after)
Definition: output.cpp:978
std::string enumerate_as_string(const Container &values, enumeration_conjunction conj=enumeration_conjunction::and_)
Definition: output.h:647
constexpr point point_west
Definition: point.h:259
constexpr point point_south
Definition: point.h:257
constexpr point point_north
Definition: point.h:253
constexpr point point_east
Definition: point.h:255
@ VPFLAG_OPAQUE
Definition: veh_type.h:71
@ VPFLAG_CARGO
Definition: veh_type.h:94

References _, enumerate_as_string(), json_flag::get(), vehicles::parts::get_all(), vpart_info::get_flags(), has_engine_conflict(), vpart_info::has_flag(), has_structural_part(), vpart_info::id, vehicle_part::info(), is_structural_part_removed(), vpart_info::location, ret_val< T >::make_failure(), ret_val< T >::make_success(), vpart_info::name(), or_, part(), part_location_structure(), parts, parts_at_relative(), point_east, point_north, point_south, point_west, json_flag::requires_flag(), string_replace(), VPFLAG_CARGO, VPFLAG_OPAQUE, and VPFLAG_POWER_TRANSFER.

Referenced by map::add_vehicle_to_map(), install_part(), item::link_to(), vehicle_prototype::save_vehicle_as_prototype(), and veh_interact::update_part_requirements().

◆ can_unmount()

ret_val< void > vehicle::can_unmount ( const vehicle_part vp_to_remove,
bool  allow_splits = false 
) const

Definition at line 1296 of file vehicle.cpp.

1297 {
1298  const vpart_info &vpi_to_remove = vp_to_remove.info();
1299  const std::vector<int> parts_here = parts_at_relative( vp_to_remove.mount, false );
1300 
1301  // make sure there are no parts which require flags from this part
1302  for( const int elem : parts_here ) {
1303  const vehicle_part &vp_here = parts[elem];
1304  for( const std::string &flag : vp_here.info().get_flags() ) {
1305  if( vpi_to_remove.has_flag( json_flag::get( flag ).requires_flag() ) ) {
1306  return ret_val<void>::make_failure( _( "Remove the attached %s first." ), vp_here.name() );
1307  }
1308  }
1309  }
1310 
1311  if( vp_to_remove.has_flag( vp_flag::animal_flag ) ) {
1312  return ret_val<void>::make_failure( _( "Remove carried animal first." ) );
1313  }
1314 
1315  if( vp_to_remove.has_flag( vp_flag::carrying_flag ) ||
1316  vp_to_remove.has_flag( vp_flag::carried_flag ) ) {
1317  return ret_val<void>::make_failure( _( "Unracking is required before removing this part." ) );
1318  }
1319 
1320  const int p = index_of_part( &vp_to_remove );
1321  if( vpi_to_remove.has_flag( "DOOR_LOCKING" ) && next_part_to_unlock( p ) >= 0 ) {
1322  return ret_val<void>::make_failure( _( "Unlock this part first." ) );
1323  }
1324 
1325  if( vpi_to_remove.location != part_location_structure ) {
1326  return ret_val<void>::make_success(); // non-structure parts don't have extra requirements
1327  }
1328 
1329  // structure parts can only be removed when no non-structure/non-cable parts are on tile
1330  bool cable_here = false;
1331  for( const int elem : parts_here ) {
1332  const vehicle_part &vp_here = parts[elem];
1333  bool vp_is_cable = vp_here.info().has_flag( VPFLAG_POWER_TRANSFER ) ||
1334  vp_here.info().has_flag( "TOW_CABLE" );
1335  cable_here = cable_here || vp_is_cable;
1336  if( vp_here.info().location != part_location_structure && !vp_is_cable ) {
1337  return ret_val<void>::make_failure( _( "Remove all other attached parts first." ) );
1338  }
1339  }
1340 
1341  // reaching here means only structure parts and/or cables left on this tile
1342  if( parts_here.size() > 1 && !cable_here ) {
1343  return ret_val<void>::make_success(); // wrecks can have more than one structure part, so it's valid for removal
1344  }
1345 
1346  // find all the vehicle's tiles adjacent to the one we're removing
1347  std::vector<vehicle_part> adjacent_parts;
1348  for( const point &offset : four_adjacent_offsets ) {
1349  const std::vector<int> parts_over_there = parts_at_relative( vp_to_remove.mount + offset, false );
1350  if( !parts_over_there.empty() ) {
1351  //Just need one part from the square to track the x/y
1352  adjacent_parts.push_back( parts[parts_over_there[0]] );
1353  }
1354  }
1355 
1356  if( adjacent_parts.empty() ) {
1357  return ret_val<void>::make_success(); // this is the only vehicle tile left, valid to remove
1358  }
1359 
1360  if( adjacent_parts.size() == 1 ) {
1361  // removing this will create invalid vehicle with only a PROTRUSION part (wing mirror, forklift etc)
1362  if( adjacent_parts[0].info().has_flag( "PROTRUSION" ) ) {
1364  _( "Remove other parts before removing last structure part." ) );
1365  }
1366  }
1367 
1368  if( !allow_splits && adjacent_parts.size() > 1 ) {
1369  // Reaching here means there is more than one adjacent tile, which means it's possible
1370  // for removal of this part to split the vehicle in two or more disjoint parts, for
1371  // example removing the middle section of a quad bike. To prevent that we'll run BFS
1372  // on every pair combination of adjacent parts to verify each pair is connected.
1373  for( size_t i = 0; i < adjacent_parts.size(); i++ ) {
1374  for( size_t j = i + 1; j < adjacent_parts.size(); j++ ) {
1375  if( !is_connected( adjacent_parts[i], adjacent_parts[j], vp_to_remove ) ) {
1376  return ret_val<void>::make_failure( _( "Removing this part would split the vehicle." ) );
1377  }
1378  }
1379  }
1380  }
1381 
1382  return ret_val<void>::make_success(); // Anything not explicitly denied is permitted
1383 }
int next_part_to_unlock(int p, bool outside=false) const
Return the index of the next part to unlock at part p's location.
Definition: vehicle.cpp:2993
bool is_connected(const vehicle_part &to, const vehicle_part &from, const vehicle_part &excluded) const
Performs a breadth-first search from one part to another, to see if a path exists between the two wit...
Definition: vehicle.cpp:1395
constexpr std::array< point, 4 > four_adjacent_offsets
Definition: point.h:333
bool has_flag(const vp_flag flag) const noexcept
Definition: vehicle.h:276
@ carried_flag
@ carrying_flag

References _, animal_flag, carried_flag, carrying_flag, four_adjacent_offsets, json_flag::get(), vpart_info::get_flags(), vpart_info::has_flag(), vehicle_part::has_flag(), index_of_part(), vehicle_part::info(), is_connected(), vpart_info::location, ret_val< T >::make_failure(), ret_val< T >::make_success(), vehicle_part::mount, vehicle_part::name(), next_part_to_unlock(), part_location_structure(), parts, parts_at_relative(), json_flag::requires_flag(), and VPFLAG_POWER_TRANSFER.

Referenced by veh_interact::can_remove_part(), veh_interact::cant_do(), and veh_app_interact::populate_app_actions().

◆ can_use_rails()

bool vehicle::can_use_rails ( ) const

Definition at line 3733 of file vehicle.cpp.

3734 {
3735  // do not allow vehicles without rail wheels or with mixed wheels
3736  bool can_use = !rail_wheelcache.empty() && wheelcache.size() == rail_wheelcache.size();
3737  if( !can_use ) {
3738  return false;
3739  }
3740  map &here = get_map();
3741  bool is_wheel_on_rail = false;
3742  for( int part_index : rail_wheelcache ) {
3743  // at least one wheel should be on track
3744  if( here.has_flag_ter_or_furn( ter_furn_flag::TFLAG_RAIL, global_part_pos3( part_index ) ) ) {
3745  is_wheel_on_rail = true;
3746  break;
3747  }
3748  }
3749  return is_wheel_on_rail;
3750 }
bool has_flag_ter_or_furn(const std::string &flag, const tripoint &p) const
Definition: map.cpp:3122

References get_map(), global_part_pos3(), map::has_flag_ter_or_furn(), rail_wheelcache, TFLAG_RAIL, and wheelcache.

Referenced by act_on_map(), on_move(), and wait().

◆ charge_battery()

int vehicle::charge_battery ( int  amount,
bool  apply_loss = true 
)

Charges batteries in connected vehicles/appliances.

Parameters
amountto charge in kJ
apply_lossif true apply wire loss when charge crosses vehicle power cables
Returns
0 or left over charge in kJ which does not fit in any connected batteries

Definition at line 5521 of file vehicle.cpp.

5522 {
5523  if( amount < 0 ) {
5524  debugmsg( "called vehicle::charge_battery(%d), potential bug", amount );
5525  return amount;
5526  }
5527  if( amount == 0 ) {
5528  return 0;
5529  }
5530  const std::map<vpart_reference, float> batteries = search_connected_batteries();
5531  if( batteries.empty() ) {
5532  return amount;
5533  }
5534  const double loss = apply_loss ? weighted_power_loss( batteries ) : 0.0;
5535  int64_t total_charge = 0; // sum of current charge of all batteries
5536  int64_t total_capacity = 0; // sum of capacity of all batteries
5537  for( const std::pair<const vpart_reference, float> &pair : batteries ) {
5538  vehicle_part &vp = pair.first.part();
5539  total_charge += vp.ammo_remaining();
5540  total_capacity += vp.ammo_capacity( ammo_battery );
5541  }
5542  const int64_t chargeable = total_capacity - total_charge;
5543  int64_t lost_amount = roll_remainder( amount * loss );
5544  int64_t lossy_amount = amount;
5545  int64_t charged = amount - lost_amount;
5546  if( charged > chargeable ) { // no battery capacity to absorb all charge, recalculate loss
5547  charged = chargeable; // cap at the maximum possible charge
5548  lost_amount = roll_remainder( charged * loss );
5549  lossy_amount = charged + lost_amount;
5550  }
5551  total_charge += charged;
5552  const int tried_charging = amount;
5553  amount -= charged + lost_amount;
5554 
5555  distribute_charge_evenly( batteries, total_charge, total_capacity );
5556 
5558  "batteries: %d, loss: %.3f, tried charging: %d kJ, actual charged: %d kJ, usable: %d kJ, lost: %d kJ, excess: %d kJ",
5559  batteries.size(), loss, tried_charging, lossy_amount, charged, lost_amount, amount );
5560 
5561  return amount; // non zero if batteries couldn't absorb the entire amount
5562 }
std::map< vpart_reference, float > search_connected_batteries()
Returns a map of connected battery references to power loss factor Keys are batteries in vehicles (in...
Definition: vehicle.cpp:5442
#define add_msg_debug(type,...)
Definition: messages.h:177
@ DF_VEHICLE
Definition: debug.h:277
int roll_remainder(double value)
Definition: rng.cpp:134
int ammo_capacity(const ammotype &ammo) const
Maximum amount of fuel, charges or ammunition that can be contained by a part.
static double weighted_power_loss(const std::map< vpart_reference, float > &batteries)
Definition: vehicle.cpp:5462
static void distribute_charge_evenly(const std::map< vpart_reference, float > &batteries, int64_t charge_kj, int64_t total_capacity_kj)
Definition: vehicle.cpp:5477

References add_msg_debug, ammo_battery, vehicle_part::ammo_capacity(), vehicle_part::ammo_remaining(), batteries, debugmsg, debugmode::DF_VEHICLE, distribute_charge_evenly(), roll_remainder(), search_connected_batteries(), and weighted_power_loss().

Referenced by item::charge_linked_batteries(), power_parts(), spell_effect::recharge_vehicle(), update_time(), and debug_menu::vehicle_battery_charge().

◆ check_falling_or_floating()

void vehicle::check_falling_or_floating ( )

Definition at line 2042 of file vehicle_move.cpp.

2043 {
2044  // If we're flying none of the rest of this matters.
2045  if( is_flying && is_rotorcraft() ) {
2046  is_falling = false;
2047  in_deep_water = false;
2048  in_water = false;
2049  return;
2050  }
2051 
2052  is_falling = true;
2053  is_flying = false;
2054  map &here = get_map();
2055 
2056  auto has_support = [&here]( const tripoint & position, const bool water_supports ) {
2057  // if we're at the bottom of the z-levels, we're supported
2058  if( position.z == -OVERMAP_DEPTH ) {
2059  return true;
2060  }
2061  // water counts as support if we're swimming and checking to see if we're falling, but
2062  // not to see if the wheels are supported at all
2063  if( here.has_flag_ter_or_furn( ter_furn_flag::TFLAG_SWIMMABLE, position ) ) {
2064  return water_supports;
2065  }
2066  if( !here.has_flag_ter_or_furn( ter_furn_flag::TFLAG_NO_FLOOR, position ) ) {
2067  return true;
2068  }
2069  tripoint below( position.xy(), position.z - 1 );
2070  return here.supports_above( below );
2071  };
2072  // Check under the wheels, if they're supported nothing else matters.
2073  int supported_wheels = 0;
2074  for( int wheel_index : wheelcache ) {
2075  const tripoint position = global_part_pos3( wheel_index );
2076  if( has_support( position, false ) ) {
2077  ++supported_wheels;
2078  }
2079  }
2080  // If half of the wheels are supported, we're not falling and we're not in water.
2081  if( supported_wheels > 0 &&
2082  static_cast<size_t>( supported_wheels ) * 2 >= wheelcache.size() ) {
2083  is_falling = false;
2084  in_water = false;
2085  in_deep_water = false;
2086  return;
2087  }
2088  // TODO: Make the vehicle "slide" towards its center of weight
2089  // when it's not properly supported
2090  const std::set<tripoint> &pts = get_points();
2091  if( pts.empty() ) {
2092  // Dirty vehicle with no parts
2093  is_falling = false;
2094  in_deep_water = false;
2095  in_water = false;
2096  is_flying = false;
2097  return;
2098  }
2099 
2100  size_t deep_water_tiles = 0;
2101  size_t water_tiles = 0;
2102  for( const tripoint &position : pts ) {
2103  deep_water_tiles += here.has_flag( ter_furn_flag::TFLAG_DEEP_WATER, position ) ? 1 : 0;
2104  water_tiles += here.has_flag( ter_furn_flag::TFLAG_SWIMMABLE, position ) ? 1 : 0;
2105  if( !is_falling ) {
2106  continue;
2107  }
2108  is_falling = !has_support( position, true );
2109  }
2110  // in_deep_water if 2/3 of the vehicle is in deep water
2111  in_deep_water = 3 * deep_water_tiles >= 2 * pts.size();
2112  // in_water if 1/2 of the vehicle is in water at all
2113  in_water = 2 * water_tiles >= pts.size();
2114 }
bool supports_above(const tripoint &p) const
Does this tile support vehicles and furniture above it.
Definition: map.cpp:2714
bool in_water
Definition: vehicle.h:2338
const std::set< tripoint > & get_points(bool force_refresh=false, bool no_fake=false) const
Definition: vehicle.cpp:7725
constexpr int OVERMAP_DEPTH
constexpr point xy() const
Definition: point.h:202

References below, get_map(), get_points(), global_part_pos3(), map::has_flag(), map::has_flag_ter_or_furn(), in_deep_water, in_water, is_falling, is_flying, is_rotorcraft(), OVERMAP_DEPTH, map::supports_above(), TFLAG_DEEP_WATER, TFLAG_NO_FLOOR, TFLAG_SWIMMABLE, wheelcache, tripoint::xy(), and tripoint::z.

Referenced by gain_moves(), game::grabbed_veh_move(), and map::move_vehicle().

◆ check_heli_ascend()

bool vehicle::check_heli_ascend ( Character p) const

Definition at line 1385 of file vehicle_move.cpp.

1386 {
1387  if( !is_rotorcraft() ) {
1388  debugmsg( "A vehicle is somehow flying without being an aircraft" );
1389  return true;
1390  }
1391  if( velocity > 0 && !is_flying_in_air() ) {
1392  p.add_msg_if_player( m_bad, _( "It would be unsafe to try and take off while you are moving." ) );
1393  return false;
1394  }
1395  if( sm_pos.z + 1 >= OVERMAP_HEIGHT ) {
1396  return false; // don't allow trying to ascend to max zlevel
1397  }
1398  map &here = get_map();
1399  creature_tracker &creatures = get_creature_tracker();
1400  for( const tripoint &pt : get_points( true ) ) {
1401  tripoint above( pt.xy(), pt.z + 1 );
1402  const optional_vpart_position ovp = here.veh_at( above );
1404  here.impassable_ter_furn( above ) ||
1405  ovp ||
1406  creatures.creature_at( above ) ) {
1408  _( "It would be unsafe to try and ascend when there are obstacles above you." ) );
1409  return false;
1410  }
1411  }
1412  return true;
1413 }
bool impassable_ter_furn(const tripoint &p) const
Definition: map.cpp:2509
bool is_flying_in_air() const
Definition: vehicle.cpp:4447
constexpr int OVERMAP_HEIGHT

References _, above, Character::add_msg_if_player(), creature_tracker::creature_at(), debugmsg, get_creature_tracker(), get_map(), get_points(), map::has_flag_ter_or_furn(), map::impassable_ter_furn(), is_flying_in_air(), is_rotorcraft(), m_bad, OVERMAP_HEIGHT, sm_pos, TFLAG_INDOORS, map::veh_at(), velocity, and tripoint::z.

Referenced by pldrive().

◆ check_heli_descend()

bool vehicle::check_heli_descend ( Character p) const

can the helicopter descend/ascend here?

Definition at line 1350 of file vehicle_move.cpp.

1351 {
1352  if( !is_rotorcraft() ) {
1353  debugmsg( "A vehicle is somehow flying without being an aircraft" );
1354  return true;
1355  }
1356  int count = 0;
1357  int air_count = 0;
1358  map &here = get_map();
1359  creature_tracker &creatures = get_creature_tracker();
1360  for( const tripoint &pt : get_points( true ) ) {
1361  tripoint below( pt.xy(), pt.z - 1 );
1362  if( pt.z < -OVERMAP_DEPTH || !here.has_flag_ter_or_furn( ter_furn_flag::TFLAG_NO_FLOOR, pt ) ) {
1363  p.add_msg_if_player( _( "You are already landed!" ) );
1364  return false;
1365  }
1366  const optional_vpart_position ovp = here.veh_at( below );
1367  if( here.impassable_ter_furn( below ) || ovp || creatures.creature_at( below ) ) {
1369  _( "It would be unsafe to try and land when there are obstacles below you." ) );
1370  return false;
1371  }
1373  air_count++;
1374  }
1375  count++;
1376  }
1377  if( velocity > 0 && air_count != count ) {
1378  p.add_msg_if_player( m_bad, _( "It would be unsafe to try and land while you are moving." ) );
1379  return false;
1380  }
1381  return true;
1382 
1383 }

References _, Character::add_msg_if_player(), below, creature_tracker::creature_at(), debugmsg, get_creature_tracker(), get_map(), get_points(), map::has_flag_ter_or_furn(), map::impassable_ter_furn(), is_rotorcraft(), m_bad, OVERMAP_DEPTH, TFLAG_NO_FLOOR, map::veh_at(), and velocity.

Referenced by pldrive().

◆ check_is_heli_landed()

bool vehicle::check_is_heli_landed ( )

Definition at line 1338 of file vehicle_move.cpp.

1339 {
1340  // @TODO - when there are chasms that extend below z-level 0 - perhaps the heli
1341  // will be able to descend into them but for now, assume z-level-0 == the ground.
1342  if( global_pos3().z == 0 ||
1343  !get_map().has_flag_ter_or_furn( ter_furn_flag::TFLAG_NO_FLOOR, global_pos3() ) ) {
1344  is_flying = false;
1345  return true;
1346  }
1347  return false;
1348 }

References get_map(), global_pos3(), is_flying, and TFLAG_NO_FLOOR.

Referenced by map::displace_vehicle().

◆ close()

void vehicle::close ( int  part_index)

Closes an openable part at the specified index.

If it's a multipart, closes all attached parts as well.

Parameters
part_indexThe index in the parts list of the part to close.

Definition at line 1210 of file vehicle_use.cpp.

1211 {
1212  vehicle_part &vp = part( part_index );
1213  if( !vp.info().has_flag( VPFLAG_OPENABLE ) ) {
1214  debugmsg( "Attempted to close non-closeable part %d (%s) on a %s!", part_index, vp.name(), name );
1215  } else {
1216  open_or_close( part_index, false );
1217  }
1218 }
void open_or_close(int part_index, bool opening)
Opens or closes an openable part at the specified index based on the @opening value passed.
@ VPFLAG_OPENABLE
Definition: veh_type.h:72

References debugmsg, vpart_info::has_flag(), vehicle_part::info(), vehicle_part::name(), name, open_or_close(), part(), and VPFLAG_OPENABLE.

Referenced by doors::close_door().

◆ coeff_air_drag()

double vehicle::coeff_air_drag ( ) const

Physical coefficients used for vehicle calculations.

coefficient of air drag in kg/m multiplied by the square of speed to calculate air drag force in N proportional to cross sectional area of the vehicle, times the density of air, times a dimensional constant based on the vehicle's shape

Definition at line 4159 of file vehicle.cpp.

4160 {
4161  if( !coeff_air_dirty ) {
4163  }
4164  constexpr double c_air_base = 0.25;
4165  constexpr double c_air_mod = 0.1;
4166  constexpr double base_height = 1.4;
4167  constexpr double aisle_height = 0.6;
4168  constexpr double fullboard_height = 0.5;
4169  constexpr double roof_height = 0.1;
4170  constexpr double windmill_height = 0.7;
4171  constexpr double sail_height = 0.8;
4172  constexpr double rotor_height = 0.6;
4173 
4174  std::vector<int> structure_indices = all_parts_at_location( part_location_structure );
4175  int width = mount_max.y - mount_min.y + 1;
4176  int length = mount_max.x - mount_min.x + 1;
4177  // a mess of lambdas to make the next bit slightly easier to read
4178  const auto d_exposed = [&]( const vehicle_part & p ) {
4179  // if it's not inside, it's a center location, and it doesn't need a roof, it's exposed
4180  if( p.info().location != part_location_center ) {
4181  return false;
4182  }
4183  return !( p.inside || p.info().has_flag( "NO_ROOF_NEEDED" ) ||
4184  p.info().has_flag( "WINDSHIELD" ) ||
4185  p.info().has_flag( "OPENABLE" ) );
4186  };
4187 
4188  const auto d_protrusion = [&]( std::vector<int> parts_at ) {
4189  if( parts_at.size() > 1 ) {
4190  return false;
4191  } else {
4192  return parts[ parts_at.front() ].info().has_flag( "PROTRUSION" );
4193  }
4194  };
4195  const auto d_check_min = [&]( int &value, const vehicle_part & p, bool test ) {
4196  value = std::min( value, test ? p.mount.x - mount_min.x : maxrow );
4197  };
4198  const auto d_check_max = [&]( int &value, const vehicle_part & p, bool test ) {
4199  value = std::max( value, test ? p.mount.x - mount_min.x : minrow );
4200  };
4201 
4202  // raycast down each column. the least drag vehicle has halfboard, windshield, seat with roof,
4203  // windshield, halfboard and is twice as long as it is wide.
4204  // find the first instance of each item and compare against the ideal configuration.
4205  std::vector<drag_column> drag( width );
4206  for( int p : structure_indices ) {
4207  if( parts[ p ].removed || parts[ p ].is_fake ) {
4208  continue;
4209  }
4210  int col = parts[ p ].mount.y - mount_min.y;
4211  std::vector<int> parts_at = parts_at_relative( parts[ p ].mount, true );
4212  d_check_min( drag[ col ].pro, parts[ p ], d_protrusion( parts_at ) );
4213  for( int pa_index : parts_at ) {
4214  const vehicle_part &pa = parts[ pa_index ];
4215  d_check_max( drag[ col ].hboard, pa, pa.info().has_flag( "HALF_BOARD" ) );
4216  d_check_max( drag[ col ].fboard, pa, pa.info().has_flag( "FULL_BOARD" ) );
4217  d_check_max( drag[ col ].aisle, pa, pa.info().has_flag( "AISLE" ) );
4218  d_check_max( drag[ col ].shield, pa, pa.info().has_flag( "WINDSHIELD" ) &&
4219  pa.is_available() );
4220  d_check_max( drag[ col ].seat, pa, pa.info().has_flag( "SEAT" ) ||
4221  pa.info().has_flag( "BED" ) );
4222  d_check_max( drag[ col ].turret, pa, pa.info().location == part_location_onroof &&
4223  !pa.info().has_flag( "SOLAR_PANEL" ) );
4224  d_check_max( drag[ col ].roof, pa, pa.info().has_flag( "ROOF" ) );
4225  d_check_max( drag[ col ].panel, pa, pa.info().has_flag( "SOLAR_PANEL" ) );
4226  d_check_max( drag[ col ].windmill, pa, pa.info().has_flag( "WIND_TURBINE" ) );
4227  d_check_max( drag[ col ].rotor, pa, pa.info().has_flag( "ROTOR" ) );
4228  d_check_max( drag[ col ].sail, pa, pa.info().has_flag( "WIND_POWERED" ) );
4229  d_check_max( drag[ col ].exposed, pa, d_exposed( pa ) );
4230  d_check_min( drag[ col ].last, pa, pa.info().has_flag( "LOW_FINAL_AIR_DRAG" ) ||
4231  pa.info().has_flag( "HALF_BOARD" ) );
4232  d_check_min( drag[ col ].lastpart, pa, true );
4233  }
4234  }
4235  double height = 0;
4236  double c_air_drag = 0;
4237  // tally the results of each row and prorate them relative to vehicle width
4238  for( drag_column &dc : drag ) {
4239  // even as m_debug you rarely want to see this
4241  "veh %: pro %d, hboard %d, fboard %d, shield %d, seat %d, roof %d, aisle %d, turret %d, panel %d, exposed %d, last %d\n",
4242  name, dc.pro, dc.hboard, dc.fboard, dc.shield, dc.seat, dc.roof, dc.aisle, dc.turret, dc.panel,
4243  dc.exposed, dc.last );
4244 
4245  double c_air_drag_c = c_air_base;
4246  // rams in front of the vehicle mildly worsens air drag
4247  c_air_drag_c += ( dc.pro > dc.hboard ) ? c_air_mod : 0;
4248  // not having halfboards in front of any windshields or fullboards moderately worsens
4249  // air drag
4250  c_air_drag_c += ( std::max( std::max( dc.hboard, dc.fboard ),
4251  dc.shield ) != dc.hboard ) ? 2 * c_air_mod : 0;
4252  // not having windshields in front of seats severely worsens air drag
4253  c_air_drag_c += ( dc.shield < dc.seat ) ? 3 * c_air_mod : 0;
4254  // missing roofs and open doors severely worsen air drag
4255  c_air_drag_c += ( dc.exposed > minrow ) ? 3 * c_air_mod : 0;
4256  // being twice as long as wide mildly reduces air drag
4257  c_air_drag_c -= ( length >= 2 * width ) ? c_air_mod : 0;
4258  // trunk doors and halfboards at the tail mildly reduce air drag
4259  c_air_drag_c -= ( dc.last == dc.lastpart ) ? c_air_mod : 0;
4260  // turrets severely worsen air drag
4261  c_air_drag_c += ( dc.turret > minrow ) ? 3 * c_air_mod : 0;
4262  // having a windmill is terrible for your drag
4263  c_air_drag_c += ( dc.windmill > minrow ) ? 5 * c_air_mod : 0;
4264  // rotors are not great for drag!
4265  c_air_drag_c += ( dc.rotor > minrow ) ? 6 * c_air_mod : 0;
4266  // having a sail is terrible for your drag
4267  c_air_drag_c += ( dc.sail > minrow ) ? 7 * c_air_mod : 0;
4268  c_air_drag += c_air_drag_c;
4269  // vehicles are 1.4m tall
4270  double c_height = base_height;
4271  // plus a bit for a roof
4272  c_height += ( dc.roof > minrow ) ? roof_height : 0;
4273  // plus a lot for an aisle
4274  c_height += ( dc.aisle > minrow ) ? aisle_height : 0;
4275  // or fullboards
4276  c_height += ( dc.fboard > minrow ) ? fullboard_height : 0;
4277  // and a little for anything on the roof
4278  c_height += ( dc.turret > minrow ) ? 2 * roof_height : 0;
4279  // solar panels are better than turrets or floodlights, though
4280  c_height += ( dc.panel > minrow ) ? roof_height : 0;
4281  // windmills are tall, too
4282  c_height += ( dc.windmill > minrow ) ? windmill_height : 0;
4283  c_height += ( dc.rotor > minrow ) ? rotor_height : 0;
4284  // sails are tall, too
4285  c_height += ( dc.sail > minrow ) ? sail_height : 0;
4286  height += c_height;
4287  }
4288  constexpr double air_density = 1.29; // kg/m^3
4289  // prorate per row height and c_air_drag
4290  height /= width;
4291  c_air_drag /= width;
4292  double cross_area = height * tile_to_width( width );
4294  "%s: height %3.2fm, width %3.2fm (%d tiles), c_air %3.2f\n", name, height,
4295  tile_to_width( width ), width, c_air_drag );
4296  // F_air_drag = c_air_drag * cross_area * 1/2 * air_density * v^2
4297  // coeff_air_resistance = c_air_drag * cross_area * 1/2 * air_density
4298  coefficient_air_resistance = std::max( 0.1, c_air_drag * cross_area * 0.5 * air_density );
4299  coeff_air_dirty = false;
4301 }
double coefficient_air_resistance
Definition: vehicle.h:2107
std::vector< int > all_parts_at_location(const std::string &location) const
Returns all parts in the vehicle that exist in the given location slot.
Definition: vehicle.cpp:3075
point mount_max
Definition: vehicle.h:2240
bool coeff_air_dirty
Definition: vehicle.h:2326
point mount_min
Definition: vehicle.h:2241
@ DF_VEHICLE_DRAG
Definition: debug.h:278
@ length
static const std::string part_location_onroof("on_roof")
static constexpr int maxrow
Definition: vehicle.cpp:4140
static const std::string part_location_center("center")
static double tile_to_width(int tiles)
Definition: vehicle.cpp:4128
static constexpr int minrow
Definition: vehicle.cpp:4139

References add_msg_debug, all_parts_at_location(), coeff_air_dirty, coefficient_air_resistance, debugmode::DF_VEHICLE_DRAG, vpart_info::has_flag(), vehicle_part::info(), vehicle_part::is_available(), last, length, vpart_info::location, max(), maxrow, min(), minrow, mount_max, mount_min, name, part_location_center(), part_location_onroof(), part_location_structure(), parts, parts_at_relative(), tile_to_width(), point::x, and point::y.

Referenced by veh_interact::display_stats(), max_ground_velocity(), max_rotor_velocity(), max_water_velocity(), safe_ground_velocity(), safe_rotor_velocity(), safe_water_velocity(), and slowdown().

◆ coeff_rolling_drag()

double vehicle::coeff_rolling_drag ( ) const

coefficient of rolling resistance multiplied by velocity to get the variable part of rolling resistance drag in N multiplied by a constant to get the constant part of rolling resistance drag in N depends on wheel design, wheel number, and vehicle weight

Definition at line 4303 of file vehicle.cpp.

4304 {
4305  if( !coeff_rolling_dirty ) {
4307  }
4308  constexpr double wheel_ratio = 1.25;
4309  constexpr double base_wheels = 4.0;
4310  // SAE J2452 measurements are in F_rr = N * C_rr * 0.000225 * ( v + 33.33 )
4311  // Don't ask me why, but it's the numbers we have. We want N * C_rr * 0.000225 here,
4312  // and N is mass * accel from gravity (aka weight)
4313  constexpr double sae_ratio = 0.000225;
4314  constexpr double newton_ratio = accel_g * sae_ratio;
4315  double wheel_factor = 0;
4316  if( wheelcache.empty() ) {
4317  wheel_factor = 50;
4318  } else {
4319  // should really sum each wheel's c_rolling_resistance * its share of vehicle mass
4320  for( int wheel : wheelcache ) {
4321  wheel_factor += parts[wheel].info().wheel_info->rolling_resistance;
4322  }
4323  // mildly increasing rolling resistance for vehicles with more than 4 wheels and mildly
4324  // decrease it for vehicles with less
4325  wheel_factor *= wheel_ratio /
4326  ( base_wheels * wheel_ratio - base_wheels + wheelcache.size() );
4327  }
4328  coefficient_rolling_resistance = newton_ratio * wheel_factor * to_kilogram( total_mass() );
4329  coeff_rolling_dirty = false;
4331 }
double coefficient_rolling_resistance
Definition: vehicle.h:2108
bool coeff_rolling_dirty
Definition: vehicle.h:2325
units::mass total_mass() const
Definition: vehicle.cpp:3472
constexpr double to_kilogram(const mass &v)
Definition: units.h:369
constexpr float accel_g
Definition: vehicle.h:226

References accel_g, coeff_rolling_dirty, coefficient_rolling_resistance, parts, units::to_kilogram(), total_mass(), and wheelcache.

Referenced by veh_interact::display_stats(), max_ground_velocity(), safe_ground_velocity(), and slowdown().

◆ coeff_water_drag()

double vehicle::coeff_water_drag ( ) const

coefficient of water drag in kg/m multiplied by the square of speed to calculate water drag force in N proportional to cross sectional area of the vehicle, times the density of water, times a dimensional constant based on the vehicle's shape

Definition at line 4501 of file vehicle.cpp.

4502 {
4503  if( !coeff_water_dirty ) {
4505  }
4506  int structural_part_count = 0;
4507  for( int structural_part_idx : all_parts_at_location( part_location_structure ) ) {
4508  const vehicle_part &vp = part( structural_part_idx );
4509  const vpart_info &vpi = vp.info();
4510  if( !vp.has_flag( vp_flag::carried_flag ) &&
4511  !vpi.has_flag( "PROTRUSION" ) ) {
4512  ++structural_part_count;
4513  }
4514  }
4515  if( structural_part_count == 0 ) {
4516  // Invalid vehicle. Return some default values. Sinks.
4517  coeff_water_dirty = false;
4518  hull_height = 0.3;
4519  draft_m = 1.0;
4522  }
4523  double hull_coverage = static_cast<double>( floating.size() ) / structural_part_count;
4524 
4525  int tile_width = mount_max.y - mount_min.y + 1;
4526  double width_m = tile_to_width( tile_width );
4527 
4528  // actual area of the hull in m^2 (handles non-rectangular shapes)
4529  // footprint area in tiles = tile width * tile length
4530  // effective footprint percent = # of structure tiles / footprint area in tiles
4531  // actual hull area in m^2 = footprint percent * length in meters * width in meters
4532  // length in meters = length in tiles
4533  // actual area in m = # of structure tiles * length in tiles * width in meters /
4534  // ( length in tiles * width in tiles )
4535  // actual area in m = # of structure tiles * width in meters / width in tiles
4536  double actual_area_m = width_m * structural_part_count / tile_width;
4537 
4538  // effective hull area is actual hull area * hull coverage
4539  double hull_area_m = actual_area_m * std::max( 0.1, hull_coverage );
4540  // Treat the hullform as a simple cuboid to calculate displaced depth of
4541  // water.
4542  // Apply Archimedes' principle (mass of water displaced is mass of vehicle).
4543  // area * depth = hull_volume = water_mass / water density
4544  // water_mass = vehicle_mass
4545  // area * depth = vehicle_mass / water_density
4546  // depth = vehicle_mass / water_density / area
4547  constexpr double water_density = 1000.0; // kg/m^3
4548  draft_m = to_kilogram( total_mass() ) / water_density / hull_area_m;
4549  // increase the streamlining as more of the boat is covered in boat boards
4550  double c_water_drag = 1.25 - hull_coverage;
4551  // hull height starts at 0.3m and goes up as you add more boat boards
4552  hull_height = 0.3 + 0.5 * hull_coverage;
4553  // F_water_drag = c_water_drag * cross_area * 1/2 * water_density * v^2
4554  // coeff_water_resistance = c_water_drag * cross_area * 1/2 * water_density
4555  coefficient_water_resistance = c_water_drag * width_m * draft_m * 0.5 * water_density;
4556  coeff_water_dirty = false;
4558 }
double coefficient_water_resistance
Definition: vehicle.h:2109

References all_parts_at_location(), carried_flag, coeff_water_dirty, coefficient_water_resistance, draft_m, floating, vpart_info::has_flag(), vehicle_part::has_flag(), hull_height, vehicle_part::info(), max(), mount_max, mount_min, part(), part_location_structure(), tile_to_width(), units::to_kilogram(), total_mass(), and point::y.

Referenced by can_float(), veh_interact::display_stats(), max_water_velocity(), safe_water_velocity(), slowdown(), water_draft(), and water_hull_height().

◆ collision()

bool vehicle::collision ( std::vector< veh_collision > &  colls,
const tripoint dp,
bool  just_detect,
bool  bash_floor = false 
)

Definition at line 697 of file vehicle_move.cpp.

700 {
701 
702  /*
703  * Big TODO:
704  * Rewrite this function so that it has "pre-collision" phase (detection)
705  * and "post-collision" phase (applying damage).
706  * Then invoke the functions cyclically (pre-post-pre-post-...) until
707  * velocity == 0 or no collision happens.
708  * Make all post-collisions in a given phase use the same momentum.
709  *
710  * How it works right now: find the first obstacle, then ram it over and over
711  * until either the obstacle is removed or the vehicle stops.
712  * Bug: when ramming a critter without enough force to send it flying,
713  * the vehicle will phase into it.
714  */
715 
716  if( dp.z != 0 && ( dp.x != 0 || dp.y != 0 ) ) {
717  // Split into horizontal + vertical
718  return collision( colls, tripoint( dp.xy(), 0 ), just_detect, bash_floor ) ||
719  collision( colls, tripoint( 0, 0, dp.z ), just_detect, bash_floor );
720  }
721 
722  if( dp.z == -1 && !bash_floor ) {
723  // First check current level, then the one below if current had no collisions
724  // Bash floors on the current one, but not on the one below.
725  if( collision( colls, tripoint_zero, just_detect, true ) ) {
726  return true;
727  }
728  }
729 
730  const bool vertical = bash_floor || dp.z != 0;
731  const int &coll_velocity = vertical ? vertical_velocity : velocity;
732  // Skip collisions when there is no apparent movement, except verticially moving rotorcraft.
733  if( coll_velocity == 0 && !is_rotorcraft() ) {
734  just_detect = true;
735  }
736 
737  const int velocity_before = coll_velocity;
738  int lowest_velocity = coll_velocity;
739  const int sign_before = sgn( velocity_before );
740  bool empty = true;
741  map &here = get_map();
742  for( int p = 0; p < part_count(); p++ ) {
743  const vehicle_part &vp = parts.at( p );
744  if( vp.removed || !vp.is_real_or_active_fake() ) {
745  continue;
746  }
747 
748  const vpart_info &info = vp.info();
749  if( !vp.is_fake && info.location != part_location_structure && !info.has_flag( VPFLAG_ROTOR ) ) {
750  continue;
751  }
752  empty = false;
753  // Coordinates of where part will go due to movement (dx/dy/dz)
754  // and turning (precalc[1])
755  const tripoint dsp = global_pos3() + dp + vp.precalc[1];
756  veh_collision coll = part_collision( p, dsp, just_detect, bash_floor );
757  if( coll.type == veh_coll_nothing && info.has_flag( VPFLAG_ROTOR ) ) {
758  size_t radius = static_cast<size_t>( std::round( info.rotor_info->rotor_diameter / 2.0f ) );
759  for( const tripoint &rotor_point : here.points_in_radius( dsp, radius ) ) {
760  veh_collision rotor_coll = part_collision( p, rotor_point, just_detect, false );
761  if( rotor_coll.type != veh_coll_nothing ) {
762  coll = rotor_coll;
763  if( just_detect ) {
764  break;
765  } else {
766  colls.push_back( rotor_coll );
767  }
768  }
769  }
770  }
771  if( coll.type == veh_coll_nothing ) {
772  continue;
773  }
774 
775  colls.push_back( coll );
776 
777  if( just_detect ) {
778  // DO insert the first collision so we can tell what was it
779  return true;
780  }
781 
782  const int velocity_after = coll_velocity;
783  // A hack for falling vehicles: restore the velocity so that it hits at full force everywhere
784  // TODO: Make this more elegant
785  if( vertical ) {
786  if( velocity_before < 0 ) {
787  lowest_velocity = std::max( lowest_velocity, coll_velocity );
788  } else {
789  lowest_velocity = std::min( lowest_velocity, coll_velocity );
790  }
791  vertical_velocity = velocity_before;
792  } else if( sgn( velocity_after ) != sign_before ) {
793  // Sign of velocity inverted, collisions would be in wrong direction
794  break;
795  }
796  }
797 
798  if( vertical ) {
799  vertical_velocity = lowest_velocity;
800  if( vertical_velocity == 0 ) {
801  is_falling = false;
802  }
803  }
804 
805  if( empty ) {
806  // HACK: Hack for dirty vehicles that didn't yet get properly removed
807  veh_collision fake_coll;
808  fake_coll.type = veh_coll_other;
809  colls.push_back( fake_coll );
810  velocity = 0;
811  vertical_velocity = 0;
812  add_msg_debug( debugmode::DF_VEHICLE_MOVE, "Collision check on a dirty vehicle %s", name );
813  return true;
814  }
815 
816  return !colls.empty();
817 }
int part_count() const
Definition: vehicle.cpp:8124
bool collision(std::vector< veh_collision > &colls, const tripoint &dp, bool just_detect, bool bash_floor=false)
veh_collision part_collision(int part, const tripoint &p, bool just_detect, bool bash_floor)
std::optional< vpslot_rotor > rotor_info
Definition: veh_type.h:298
constexpr int sgn(const T x)
Definition: enums.h:10
@ DF_VEHICLE_MOVE
Definition: debug.h:279
veh_coll_type type
Definition: vehicle.h:141
bool is_fake
Definition: vehicle.h:571
bool is_real_or_active_fake() const
Definition: vehicle.h:578
@ VPFLAG_ROTOR
Definition: veh_type.h:80
@ veh_coll_nothing
Definition: vehicle.h:112
@ veh_coll_other
Definition: vehicle.h:116
static const std::string part_location_structure("structure")

References add_msg_debug, debugmode::DF_VEHICLE_MOVE, get_map(), global_pos3(), vpart_info::has_flag(), vehicle_part::info(), vehicle_part::is_fake, is_falling, vehicle_part::is_real_or_active_fake(), is_rotorcraft(), vpart_info::location, max(), min(), name, part_collision(), part_count(), part_location_structure(), parts, map::points_in_radius(), vehicle_part::precalc, vehicle_part::removed, vpart_info::rotor_info, round(), sgn(), tripoint, tripoint_zero, veh_collision::type, veh_coll_nothing, veh_coll_other, velocity, vertical_velocity, VPFLAG_ROTOR, tripoint::x, tripoint::xy(), tripoint::y, and tripoint::z.

Referenced by game::grabbed_veh_move(), and map::move_vehicle().

◆ connect()

void vehicle::connect ( const tripoint source_pos,
const tripoint target_pos 
)

Definition at line 556 of file vehicle_use.cpp.

557 {
558  map &here = get_map();
559  const optional_vpart_position sel_vp = here.veh_at( target_pos );
560  const optional_vpart_position prev_vp = here.veh_at( source_pos );
561 
562  if( !sel_vp ) {
563  return;
564  }
565  if( &sel_vp->vehicle() == &prev_vp->vehicle() ) {
566  return ;
567  }
568 
569  item cord( "power_cord" );
570  if( !cord.link_to( prev_vp, sel_vp, link_state::vehicle_port ).success() ) {
571  debugmsg( "Failed to connect the %s, it tried to make an invalid connection!", cord.tname() );
572  }
573 }

References debugmsg, get_map(), item::link_to(), ret_val_common::success(), item::tname(), map::veh_at(), and vehicle_port.

Referenced by place_appliance().

◆ connected_battery_power_level()

std::pair< int, int > vehicle::connected_battery_power_level ( ) const

Definition at line 5026 of file vehicle.cpp.

5027 {
5028  int total_epower_remaining = 0;
5029  int total_epower_capacity = 0;
5030 
5031  for( const std::pair<const vehicle *const, float> &pair : search_connected_vehicles() ) {
5032  int epower_remaining;
5033  int epower_capacity;
5034  std::tie( epower_remaining, epower_capacity ) = pair.first->battery_power_level();
5035  total_epower_remaining += epower_remaining;
5036  total_epower_capacity += epower_capacity;
5037  }
5038 
5039  return std::make_pair( total_epower_remaining, total_epower_capacity );
5040 }

References search_connected_vehicles().

Referenced by active_reactor_epower(), item::ammo_capacity(), item::ammo_remaining(), item::charge_linked_batteries(), and power_parts().

◆ consume_fuel()

void vehicle::consume_fuel ( int  load,
bool  idling 
)

Definition at line 4864 of file vehicle.cpp.

4865 {
4866  double st = strain();
4867  for( const auto &fuel_pr : fuel_usage() ) {
4868  const itype_id &ft = fuel_pr.first;
4869  if( idling && ft == fuel_type_battery ) {
4870  continue;
4871  }
4872 
4873  units::energy to_consume = fuel_pr.second * 1_seconds;
4874  to_consume *= load * ( 1 + st * st * 100 ) / 1000;
4875  auto inserted = fuel_used_last_turn.insert( { ft, 0_J } );
4876  inserted.first->second += to_consume;
4877  units::energy remainder = fuel_remainder[ ft ];
4878  to_consume -= remainder;
4879 
4880  if( to_consume > 0_J ) {
4881  fuel_remainder[ ft ] = drain_energy( ft, to_consume ) - to_consume;
4882  } else {
4883  fuel_remainder[ ft ] = -to_consume;
4884  }
4885  }
4886  // Only process muscle power and training things when moving.
4887  if( idling ) {
4888  return;
4889  }
4890  Character &player_character = get_player_character();
4891 
4892  // if engine is under load, player is actively piloting a vehicle, so train appropriate vehicle proficiency
4893  if( load > 0 ) {
4894  practice_pilot_proficiencies( player_character, in_deep_water );
4895  }
4896 
4897  if( load > 0 && fuel_left( fuel_type_muscle ) > 0 &&
4898  player_character.has_effect( effect_winded ) ) {
4899  cruise_velocity = 0;
4900  if( velocity == 0 ) {
4901  stop();
4902  }
4903  }
4904  // we want this to update the activity level whenever we're using muscle power to move
4905  if( load > 0 && fuel_left( fuel_type_muscle ) > 0 ) {
4906  player_character.set_activity_level( ACTIVE_EXERCISE );
4907  //do this as a function of current load
4908  // But only if the player is actually there!
4909  int eff_load = load / 10;
4910  int mod = 4 * st; // strain
4911  const int base_staminaRegen = static_cast<int>
4912  ( get_option<float>( "PLAYER_BASE_STAMINA_REGEN_RATE" ) );
4913  const int actual_staminaRegen = static_cast<int>( base_staminaRegen *
4914  player_character.get_cardiofit() / player_character.get_cardio_acc_base() );
4915  int base_burn = actual_staminaRegen - 3;
4916  base_burn = std::max( eff_load / 3, base_burn );
4917  //charge bionics when using muscle engine
4918  const item muscle( "muscle" );
4919  for( const bionic_id &bid : player_character.get_bionic_fueled_with_muscle() ) {
4920  if( player_character.has_active_bionic( bid ) ) { // active power gen
4921  // more pedaling = more power
4922  player_character.mod_power_level( muscle.fuel_energy() *
4923  bid->fuel_efficiency *
4924  load / 1000 );
4925  mod += eff_load / 5;
4926  } else { // passive power gen
4927  player_character.mod_power_level( muscle.fuel_energy() *
4928  bid->passive_fuel_efficiency *
4929  load / 1000 );
4930  mod += eff_load / 10;
4931  }
4932  }
4933  // decreased stamina burn scalable with load
4934  if( player_character.has_active_bionic( bio_jointservo ) ) {
4935  player_character.mod_power_level( units::from_kilojoule( static_cast<std::int64_t>( -std::max(
4936  eff_load / 20, 1 ) ) ) );
4937  mod -= std::max( eff_load / 5, 5 );
4938  }
4939 
4940  player_character.mod_stamina( -( base_burn + mod ) );
4941  add_msg_debug( debugmode::DF_VEHICLE, "Load: %d", load );
4942  add_msg_debug( debugmode::DF_VEHICLE, "Mod: %d", mod );
4943  add_msg_debug( debugmode::DF_VEHICLE, "Burn: %d", -( base_burn + mod ) );
4944 
4945  // player is actively powering a muscle engine, so train cycling proficiency
4946  practice_athletic_proficiency( player_character );
4947  }
4948 }
void mod_power_level(const units::energy &npower)
Definition: character.cpp:2852
std::vector< bionic_id > get_bionic_fueled_with_muscle() const
Return bionic_id of bionics able to use it as fuel.
Definition: bionics.cpp:3273
int get_cardio_acc_base() const
Definition: character.cpp:7139
void mod_stamina(int mod)
Definition: character.cpp:6940
int get_cardiofit() const
Definition: character.cpp:7088
void set_activity_level(float new_level)
Definition: character.cpp:6547
bool has_active_bionic(const bionic_id &b) const
Returns true if the player has the entered bionic id and it is powered on.
Definition: bionics.cpp:2658
std::map< itype_id, units::power > fuel_usage() const
Maps used fuel to its basic (unscaled by load/strain) consumption.
Definition: vehicle.cpp:4834
std::map< itype_id, units::energy > fuel_remainder
Definition: vehicle.h:2214
float strain() const
Definition: vehicle.cpp:4612
std::map< itype_id, units::energy > fuel_used_last_turn
Definition: vehicle.h:2215
units::energy drain_energy(const itype_id &ftype, units::energy wanted_energy)
Consumes enough fuel by energy content.
Definition: vehicle.cpp:4847
int cruise_velocity
Definition: vehicle.h:2284
constexpr float ACTIVE_EXERCISE
void load(const JsonObject &jo, const std::string &src)
constexpr quantity< value_type, energy_in_millijoule_tag > from_kilojoule(const value_type v)
Definition: units.h:555
void practice_pilot_proficiencies(Character &p, bool &boating)
Definition: vehicle.cpp:4950
static const efftype_id effect_winded("winded")
void practice_athletic_proficiency(Character &p)
Definition: vehicle.cpp:4960
static const itype_id fuel_type_muscle("muscle")
static const bionic_id bio_jointservo("bio_jointservo")

References ACTIVE_EXERCISE, add_msg_debug, bio_jointservo, cruise_velocity, debugmode::DF_VEHICLE, drain_energy(), effect_winded, units::from_kilojoule(), item::fuel_energy(), fuel_left(), fuel_remainder, fuel_type_battery, fuel_type_muscle, fuel_usage(), fuel_used_last_turn, Character::get_bionic_fueled_with_muscle(), Character::get_cardio_acc_base(), Character::get_cardiofit(), get_player_character(), Character::has_active_bionic(), Creature::has_effect(), in_deep_water, ammo_effects::load(), max(), Character::mod_power_level(), Character::mod_stamina(), practice_athletic_proficiency(), practice_pilot_proficiencies(), Character::set_activity_level(), stop(), strain(), and velocity.

Referenced by idle(), and thrust().

◆ consumption_per_hour()

int vehicle::consumption_per_hour ( const itype_id ftype,
units::energy  fuel_per_s 
) const

Definition at line 3684 of file vehicle.cpp.

3685 {
3686  item fuel = item( ftype );
3687  if( fuel_per_s == 0_J || fuel.has_flag( flag_PERPETUAL ) || !engine_on ) {
3688  return 0;
3689  }
3690 
3691  units::energy energy_per_h = fuel_per_s * 3600;
3692  units::energy energy_per_liter = fuel.get_base_material().get_fuel_data().energy;
3693 
3694  return -1000 * energy_per_h / energy_per_liter;
3695 }
bool has_flag(const flag_id &flag) const
Definition: item.cpp:7578
const material_type & get_base_material() const
Get the basic (main) material of this item.
Definition: item.cpp:10349
fuel_data get_fuel_data() const
Definition: material.cpp:351
const flag_id flag_PERPETUAL("PERPETUAL")
units::energy energy
Energy of the fuel per litre.
Definition: material.h:60

References fuel_data::energy, engine_on, flag_PERPETUAL, item::get_base_material(), material_type::get_fuel_data(), item::has_flag(), and item.

Referenced by print_fuel_indicator().

◆ control_doors()

void vehicle::control_doors ( )

Definition at line 136 of file vehicle_use.cpp.

137 {
138  const auto open_or_close_all = [this]( bool new_open, const std::string & require_flag ) {
139  for( const vpart_reference &vpr_motor : get_avail_parts( "DOOR_MOTOR" ) ) {
140  const int motorized_idx = new_open
141  ? next_part_to_open( vpr_motor.part_index() )
142  : next_part_to_close( vpr_motor.part_index() );
143  if( motorized_idx == -1 ) {
144  continue;
145  }
146  vehicle_part &vp = part( motorized_idx );
147  if( !require_flag.empty() && !vp.info().has_flag( require_flag ) ) {
148  continue;
149  }
150  if( new_open || can_close( motorized_idx, get_player_character() ) ) {
151  open_or_close( motorized_idx, new_open );
152  }
153  }
154  };
155  const auto lock_or_unlock_all = [this]( bool new_lock, const std::string & require_flag ) {
156  for( const vpart_reference &vpr_motor : get_avail_parts( "DOOR_MOTOR" ) ) {
157  const int motorized_idx = new_lock
158  ? next_part_to_lock( vpr_motor.part_index() )
159  : next_part_to_unlock( vpr_motor.part_index() );
160  if( motorized_idx == -1 ) {
161  continue;
162  }
163  vehicle_part &vp = part( motorized_idx );
164  if( !require_flag.empty() && !vp.info().has_flag( require_flag ) ) {
165  continue;
166  }
167  lock_or_unlock( motorized_idx, new_lock );
168  }
169  };
170 
171  const auto add_openable = [this]( veh_menu & menu, int vp_idx ) {
172  if( vp_idx == -1 ) {
173  return;
174  }
175  const vehicle_part &vp = part( vp_idx );
176  const std::string actname = vp.open ? _( "Close" ) : _( "Open" );
177  const bool open = !vp.open;
178  menu.add( string_format( "%s %s", actname, vp.name() ) )
179  .hotkey_auto()
180  .location( global_part_pos3( vp ) )
181  .keep_menu_open()
182  .on_submit( [this, vp_idx, open] {
183  if( can_close( vp_idx, get_player_character() ) )
184  {
185  open_or_close( vp_idx, open );
186  }
187  } );
188  };
189 
190  const auto add_lockable = [this]( veh_menu & menu, int vp_idx ) {
191  if( vp_idx == -1 ) {
192  return;
193  }
194  const vehicle_part &vp = part( vp_idx );
195  const std::string actname = vp.locked ? _( "Unlock" ) : _( "Lock" );
196  const bool lock = !vp.locked;
197  menu.add( string_format( "%s %s", actname, vp.name() ) )
198  .hotkey_auto()
199  .location( global_part_pos3( vp ) )
200  .keep_menu_open()
201  .on_submit( [this, vp_idx, lock] {
202  lock_or_unlock( vp_idx, lock );
203  } );
204  };
205 
206  veh_menu menu( this, _( "Select door to toggle" ) );
207 
208  do {
209  menu.reset();
210 
211  menu.add( _( "Open all curtains" ) )
212  .hotkey_auto()
214  .on_submit( [&open_or_close_all] { open_or_close_all( true, "CURTAIN" ); } );
215 
216  menu.add( _( "Open all curtains and doors" ) )
217  .hotkey_auto()
219  .on_submit( [&open_or_close_all, &lock_or_unlock_all] {
220  lock_or_unlock_all( false, "LOCKABLE_DOOR" );
221  open_or_close_all( true, "" );
222  } );
223  menu.add( _( "Close all doors" ) )
224  .hotkey_auto()
226  .on_submit( [&open_or_close_all] { open_or_close_all( false, "DOOR" ); } );
227 
228  menu.add( _( "Close all curtains and doors" ) )
229  .hotkey_auto()
231  .on_submit( [&open_or_close_all] { open_or_close_all( false, "" ); } );
232 
233  for( const vpart_reference &vp_motor : get_avail_parts( "DOOR_MOTOR" ) ) {
234  add_openable( menu, next_part_to_open( vp_motor.part_index() ) );
235  add_openable( menu, next_part_to_close( vp_motor.part_index() ) );
236  add_lockable( menu, next_part_to_unlock( vp_motor.part_index() ) );
237  add_lockable( menu, next_part_to_lock( vp_motor.part_index() ) );
238  }
239 
240  if( menu.get_items_size() == 4 ) {
241  debugmsg( "vehicle::control_doors called but no door motors found" );
242  return;
243  }
244  } while( menu.query() );
245 }
bool query()
Definition: veh_utils.cpp:324
size_t get_items_size() const
Definition: veh_utils.cpp:264
void reset(bool keep_last_selected=true)
Definition: veh_utils.cpp:287
void lock(int part_index)
Locks a lockable, closed part at the specified index.
bool can_close(int part_index, Character &who)
void open(int part_index)
Opens an openable part at the specified index.
int next_part_to_open(int p, bool outside=false) const
Return the index of the next part to open at p's location.
Definition: vehicle.cpp:2946
int next_part_to_lock(int p, bool outside=false) const
Return the index of the next part to lock at part p's location.
Definition: vehicle.cpp:2974
void lock_or_unlock(int part_index, bool locking)
Locks or unlocks a lockable door part at the specified index based on the @locking value passed.
int next_part_to_close(int p, bool outside=false) const
Return the index of the next part to close at p
Definition: vehicle.cpp:2928
veh_menu_item & location(const std::optional< tripoint > &location)
Definition: veh_utils.cpp:240
bool locked
door is locked
Definition: vehicle.h:516
bool open
door is open
Definition: vehicle.h:513

References _, veh_menu::add(), can_close(), debugmsg, get_avail_parts(), veh_menu::get_items_size(), get_player_character(), global_part_pos3(), vpart_info::has_flag(), veh_menu_item::hotkey_auto(), vehicle_part::info(), veh_menu_item::keep_menu_open(), veh_menu_item::location(), lock(), lock_or_unlock(), vehicle_part::locked, vehicle_part::name(), next_part_to_close(), next_part_to_lock(), next_part_to_open(), next_part_to_unlock(), veh_menu_item::on_submit(), vehicle_part::open, open(), open_or_close(), part(), Creature::pos(), pos, veh_menu::query(), veh_menu::reset(), and string_format().

Referenced by build_electronics_menu().

◆ control_engines()

void vehicle::control_engines ( )

Definition at line 380 of file vehicle_use.cpp.

381 {
382  bool dirty = false;
383 
384  veh_menu menu( this, _( "Toggle which?" ) );
385  do {
386  menu.reset();
387  for( const int engine_idx : engines ) {
388  const vehicle_part &vp = parts[engine_idx];
389  for( const itype_id &fuel_type : vp.info().engine_info->fuel_opts ) {
390  const bool is_active = vp.enabled && vp.fuel_current() == fuel_type;
391  const bool has_fuel = is_perpetual_type( vp ) || fuel_left( fuel_type );
392  menu.add( string_format( "[%s] %s %s", is_active ? "x" : " ", vp.name(), fuel_type->nname( 1 ) ) )
393  .enable( vp.is_available() && has_fuel )
394  .keep_menu_open()
395  .on_submit( [this, engine_idx, fuel_type, &dirty] {
396  vehicle_part &vp = parts[engine_idx];
397  if( vp.fuel_current() == fuel_type )
398  {
399  vp.enabled = !vp.enabled;
400  } else
401  {
402  vp.fuel_set( fuel_type );
403  }
404  dirty = true;
405  } );
406  }
407  }
408  } while( menu.query() );
409 
410  if( !dirty ) {
411  return;
412  }
413 
414  bool engines_were_on = engine_on;
415  for( const int p : engines ) {
416  const vehicle_part &vp = parts[p];
417  engine_on |= vp.enabled;
418  }
419 
420  // if current velocity greater than new configuration safe speed
421  // drop down cruise velocity.
422  int safe_vel = safe_velocity();
423  if( velocity > safe_vel ) {
424  cruise_velocity = safe_vel;
425  }
426 
427  if( engines_were_on && !engine_on ) {
428  add_msg( _( "You turn off the %s's engines to change their configurations." ), name );
429  } else if( !get_player_character().controlling_vehicle ) {
430  add_msg( _( "You change the %s's engine configuration." ), name );
431  }
432 
433  if( engine_on ) {
434  start_engines();
435  }
436 }
int safe_velocity(bool fueled=true) const
Definition: vehicle.cpp:3972
itype_id fuel_current() const
Type of fuel used by an engine.

References _, veh_menu::add(), add_msg(), cruise_velocity, veh_menu_item::enable(), vehicle_part::enabled, vpart_info::engine_info, engine_on, engines, vehicle_part::fuel_current(), fuel_left(), get_player_character(), vehicle_part::info(), vehicle_part::is_available(), is_perpetual_type(), veh_menu_item::keep_menu_open(), vehicle_part::name(), name, veh_menu_item::on_submit(), parts, veh_menu::query(), veh_menu::reset(), safe_velocity(), start_engines(), string_format(), and velocity.

Referenced by build_interact_menu().

◆ coord_translate() [1/3]

point vehicle::coord_translate ( const point p) const

◆ coord_translate() [2/3]

void vehicle::coord_translate ( const units::angle dir,
const point pivot,
const point p,
tripoint q 
) const

Definition at line 3308 of file vehicle.cpp.

3310 {
3311  tileray tdir( dir );
3312  tdir.advance( p.x - pivot.x );
3313  q.x = tdir.dx() + tdir.ortho_dx( p.y - pivot.y );
3314  q.y = tdir.dy() + tdir.ortho_dy( p.y - pivot.y );
3315 }

References tileray::advance(), tileray::dx(), tileray::dy(), tileray::ortho_dx(), tileray::ortho_dy(), point::x, tripoint::x, point::y, and tripoint::y.

◆ coord_translate() [3/3]

void vehicle::coord_translate ( tileray  tdir,
const point pivot,
const point p,
tripoint q 
) const

Definition at line 3317 of file vehicle.cpp.

3319 {
3320  tdir.clear_advance();
3321  tdir.advance( p.x - pivot.x );
3322  q.x = tdir.dx() + tdir.ortho_dx( p.y - pivot.y );
3323  q.y = tdir.dy() + tdir.ortho_dy( p.y - pivot.y );
3324 }
int ortho_dx(int od) const
Definition: tileray.cpp:88
int ortho_dy(int od) const
Definition: tileray.cpp:94
void clear_advance()
Definition: tileray.cpp:56

References tileray::advance(), tileray::clear_advance(), tileray::dx(), tileray::dy(), tileray::ortho_dx(), tileray::ortho_dy(), point::x, tripoint::x, point::y, and tripoint::y.

◆ crash_terrain_around()

void vehicle::crash_terrain_around ( )

Definition at line 957 of file vehicle_use.cpp.

958 {
959  if( total_power() <= 0_W ) {
960  return;
961  }
962  map &here = get_map();
963  for( const vpart_reference &vp : get_enabled_parts( "CRASH_TERRAIN_AROUND" ) ) {
964  tripoint crush_target( 0, 0, -OVERMAP_LAYERS );
965  const tripoint start_pos = vp.pos();
966  const vpslot_terrain_transform &ttd = *vp.info().transform_terrain_info;
967  for( size_t i = 0; i < eight_horizontal_neighbors.size() &&
968  crush_target.z == -OVERMAP_LAYERS; i++ ) {
969  tripoint cur_pos = start_pos + eight_horizontal_neighbors[i];
970  bool busy_pos = false;
971  for( const vpart_reference &vp_tmp : get_all_parts() ) {
972  busy_pos |= vp_tmp.pos() == cur_pos;
973  }
974  for( const std::string &flag : ttd.pre_flags ) {
975  if( here.has_flag( flag, cur_pos ) && !busy_pos ) {
976  crush_target = cur_pos;
977  break;
978  }
979  }
980  }
981  //target chosen
982  if( crush_target.z != -OVERMAP_LAYERS ) {
983  velocity = 0;
984  cruise_velocity = 0;
985  here.destroy( crush_target );
986  sounds::sound( crush_target, 500, sounds::sound_t::combat, _( "Clanggggg!" ), false,
987  "smash_success", "hit_vehicle" );
988  }
989  }
990 }
void destroy(const tripoint &p, bool silent=false)
Keeps bashing a square until it can't be bashed anymore.
Definition: map.cpp:4394
units::power total_power(bool fueled=true, bool safe=false) const
Definition: vehicle.cpp:3697
vehicle_part_with_feature_range< std::string > get_enabled_parts(std::string feature) const
Yields a range of parts of this vehicle that each have the given feature and are enabled and availabl...
Definition: vehicle.cpp:3050
constexpr int OVERMAP_LAYERS
const std::array< tripoint, 8 > eight_horizontal_neighbors
Definition: point.h:354
std::set< std::string > pre_flags
Definition: veh_type.h:164

References _, sounds::combat, cruise_velocity, map::destroy(), eight_horizontal_neighbors, get_all_parts(), get_enabled_parts(), get_map(), map::has_flag(), OVERMAP_LAYERS, vpslot_terrain_transform::pre_flags, sounds::sound(), total_power(), velocity, and tripoint::z.

Referenced by idle().

◆ cruise_thrust()

void vehicle::cruise_thrust ( int  amount)

Definition at line 629 of file vehicle_move.cpp.

630 {
631  if( amount == 0 ) {
632  return;
633  }
634  int safe_vel = safe_velocity();
635  int max_vel = autopilot_on ? safe_velocity() : max_velocity();
636  int max_rev_vel = max_reverse_velocity();
637 
638  //if the safe velocity is between the cruise velocity and its next value, set to safe velocity
639  if( ( cruise_velocity < safe_vel && safe_vel < ( cruise_velocity + amount ) ) ||
640  ( cruise_velocity > safe_vel && safe_vel > ( cruise_velocity + amount ) ) ) {
641  cruise_velocity = safe_vel;
642  } else {
643  if( amount < 0 && ( cruise_velocity == safe_vel || cruise_velocity == max_vel ) ) {
644  // If coming down from safe_velocity or max_velocity decrease by one so
645  // the rounding below will drop velocity to a multiple of amount.
646  cruise_velocity += -1;
647  } else if( amount > 0 && cruise_velocity == max_rev_vel ) {
648  // If increasing from max_rev_vel, do the opposite.
649  cruise_velocity += 1;
650  } else {
651  // Otherwise just add the amount.
652  cruise_velocity += amount;
653  }
654  // Integer round to lowest multiple of amount.
655  // The result is always equal to the original or closer to zero,
656  // even if negative
657  cruise_velocity = ( cruise_velocity / std::abs( amount ) ) * std::abs( amount );
658  }
659  // Can't have a cruise speed faster than max speed
660  // or reverse speed faster than max reverse speed.
661  if( cruise_velocity > max_vel ) {
662  cruise_velocity = max_vel;
663  } else if( cruise_velocity < max_rev_vel ) {
664  cruise_velocity = max_rev_vel;
665  }
666 }
int max_velocity(bool fueled=true) const
Definition: vehicle.cpp:3922
bool autopilot_on
Definition: vehicle.h:2360
int max_reverse_velocity(bool fueled=true) const
Definition: vehicle.cpp:3933

References abs(), autopilot_on, cruise_velocity, max_reverse_velocity(), max_velocity(), and safe_velocity().

Referenced by pldrive(), and selfdrive().

◆ current_acceleration()

int vehicle::current_acceleration ( bool  fueled = true) const

Definition at line 3849 of file vehicle.cpp.

3850 {
3851  return acceleration( fueled, std::abs( velocity ) );
3852 }
int acceleration(bool fueled=true, int at_vel_in_vmi=-1) const
Definition: vehicle.cpp:3839

References abs(), acceleration(), and velocity.

Referenced by smart_controller_handle_turn(), and thrust().

◆ damage()

int vehicle::damage ( map here,
int  p,
int  dmg,
const damage_type_id type = damage_type_id( "bash" ),
bool  aimed = true 
)

Definition at line 7143 of file vehicle.cpp.

7144 {
7145  if( dmg < 1 ) {
7146  return dmg;
7147  }
7148 
7149  p = get_non_fake_part( p );
7150  const vehicle_part &vp_initial = part( p );
7151  const std::vector<int> parts_here = parts_at_relative( vp_initial.mount, true );
7152  if( parts_here.empty() ) {
7153  return dmg; // We ran out of non removed parts at this location already.
7154  }
7155 
7156  if( !aimed ) {
7157  bool found_obstacle = false;
7158  for( const int p_here : parts_here ) {
7159  const vehicle_part &vp_here = part( p_here );
7160  const vpart_info &vpi_here = vp_here.info();
7161  if( vpi_here.has_flag( "OBSTACLE" ) && ( !vpi_here.has_flag( "OPENABLE" ) || !vp_here.open ) ) {
7162  found_obstacle = true;
7163  break;
7164  }
7165  }
7166  if( !found_obstacle ) {
7167  return dmg; // not aimed at this tile and no obstacle here -- fly through
7168  }
7169  }
7170 
7171  int target_part = vp_initial.info().has_flag( VPFLAG_ROTOR ) ? p : random_entry( parts_here );
7172 
7173  // Parts integrated inside a door or board are protected by boards and closed doors
7174  if( part( target_part ).info().has_flag( "BOARD_INTERNAL" ) ) {
7175  int strongest_board_durability = INT_MIN;
7176  for( const int part : parts_here ) {
7177  const vehicle_part &vp_here = parts[part];
7178  const vpart_info &vpi_here = vp_here.info();
7179  if( vpi_here.has_flag( "FULL_BOARD" ) || vpi_here.has_flag( "HALF_BOARD" ) ||
7180  ( vpi_here.has_flag( "OPENABLE" ) && !vp_here.open ) ) {
7181  if( vpi_here.durability > strongest_board_durability ) {
7182  target_part = part;
7183  strongest_board_durability = vpi_here.durability;
7184  }
7185  }
7186  }
7187  }
7188 
7189  vehicle_part &vp_target = part( target_part );
7190  const vpart_info &vpi_target = vp_target.info();
7191 
7192  const int armor_part = part_with_feature( vp_initial.mount, "ARMOR", true );
7193  if( armor_part < 0 ) { // Not covered by armor -- damage part
7194  return damage_direct( here, vp_target, dmg, type );
7195  }
7196 
7197  vehicle_part &vp_armor = part( armor_part );
7198  const vpart_info &vpi_armor = vp_armor.info();
7199  // Covered by armor -- hit both armor and part, but reduce damage by armor's reduction
7200  const int protection = type->no_resist ? 0 : vpi_armor.damage_reduction.at( type );
7201  // Parts on roof aren't protected
7202  const bool overhead = vpi_target.has_flag( "ROOF" ) || vpi_target.location == "on_roof";
7203  // Calling damage_direct may remove the damaged part completely, therefore the
7204  // other index (target_part) becomes wrong if target_part > armor_part.
7205  // Damaging the part with the higher index first is safe, as removing a part
7206  // only changes indices after the removed part.
7207  if( armor_part < target_part ) {
7208  damage_direct( here, vp_target, overhead ? dmg : dmg - protection, type );
7209  return damage_direct( here, vp_armor, dmg, type );
7210  } else {
7211  const int damage_dealt = damage_direct( here, vp_armor, dmg, type );
7212  damage_direct( here, vp_target, overhead ? dmg : dmg - protection, type );
7213  return damage_dealt;
7214  }
7215 }
int damage_direct(map &here, vehicle_part &vp, int dmg, const damage_type_id &type=damage_type_id("pure"))
Definition: vehicle.cpp:7457
std::unordered_map< damage_type_id, float > damage_reduction
Flat decrease of damage of a given type.
Definition: veh_type.h:361

References damage_direct(), vpart_info::damage_reduction, vpart_info::durability, get_non_fake_part(), vpart_info::has_flag(), vehicle_part::info(), vpart_info::location, vehicle_part::mount, vehicle_part::open, part(), part_with_feature(), parts, parts_at_relative(), random_entry(), type, and VPFLAG_ROTOR.

Referenced by map::move_vehicle(), operate_planter(), transform_terrain(), and map::vehicle_vehicle_collision().

◆ damage_all()

void vehicle::damage_all ( int  dmg1,
int  dmg2,
const damage_type_id type,
const point impact 
)

Definition at line 7217 of file vehicle.cpp.

7218 {
7219  if( dmg2 < dmg1 ) {
7220  std::swap( dmg1, dmg2 );
7221  }
7222 
7223  if( dmg1 < 1 ) {
7224  return;
7225  }
7226 
7227  for( const vpart_reference &vpr : get_all_parts() ) {
7228  vehicle_part &vp = vpr.part();
7229  const vpart_info &vpi = vp.info();
7230  const int distance = 1 + square_dist( vp.mount, impact );
7231  if( distance > 1 ) {
7232  int net_dmg = rng( dmg1, dmg2 ) / ( distance * distance );
7233  if( vpi.location != part_location_structure || !vpi.has_flag( "PROTRUSION" ) ) {
7234  const int shock_absorber = part_with_feature( vp.mount, "SHOCK_ABSORBER", true );
7235  if( shock_absorber >= 0 ) {
7236  const vehicle_part &vp_shock_absorber = part( shock_absorber );
7237  net_dmg = std::max( 0, net_dmg - vp_shock_absorber.info().bonus );
7238  }
7239  }
7240  damage_direct( get_map(), vp, net_dmg, type );
7241  }
7242  }
7243 }
int bonus
Definition: veh_type.h:445
int square_dist(const coords::coord_point< Point, Origin, Scale, LhsInBounds > &loc1, const coords::coord_point< Point, Origin, Scale, RhsInBounds > &loc2)
Definition: coordinates.h:755
void swap(colony< element_type, element_allocator_type, element_skipfield_type > &a, colony< element_type, element_allocator_type, element_skipfield_type > &b) COLONY_NOEXCEPT_SWAP(element_allocator_type)
Swaps colony A's contents with that of colony B.
Definition: colony.h:3505

References vpart_info::bonus, damage_direct(), get_all_parts(), get_map(), vpart_info::has_flag(), vehicle_part::info(), vpart_info::location, max(), vehicle_part::mount, part(), part_location_structure(), part_with_feature(), rng(), square_dist(), cata::swap(), and type.

Referenced by map::move_vehicle(), and map::vehicle_vehicle_collision().

◆ damage_direct()

int vehicle::damage_direct ( map here,
vehicle_part vp,
int  dmg,
const damage_type_id type = damage_type_id( "pure" ) 
)
private

Definition at line 7457 of file vehicle.cpp.

7458 {
7459  if( vp.removed ) {
7460  return dmg; // part is already dead
7461  }
7462  const vpart_info &vpi = vp.info();
7463  const tripoint vppos = global_part_pos3( vp );
7464  // If auto-driving and damage happens, bail out
7465  if( is_autodriving ) {
7466  stop_autodriving();
7467  }
7468  here.memory_cache_dec_set_dirty( vppos, true );
7469  if( vp.is_broken() ) {
7470  return break_off( here, vp, dmg );
7471  }
7472 
7473  int tsh = std::min( 20, vpi.durability / 10 );
7474  if( dmg < tsh && type != damage_pure ) {
7475  if( type == damage_heat && vp.is_fuel_store() ) {
7476  explode_fuel( vp, type );
7477  }
7478 
7479  return dmg;
7480  }
7481 
7482  if( !type->no_resist ) {
7483  dmg -= std::min<int>( dmg, vpi.damage_reduction.at( type ) );
7484  }
7485  int dres = dmg - vp.hp();
7486  if( mod_hp( vp, -dmg ) ) {
7487  if( is_flyable() && !rotors.empty() && !vpi.has_flag( VPFLAG_SIMPLE_PART ) ) {
7488  // If we break a part, we can no longer fly the vehicle.
7489  set_flyable( false );
7490  }
7491 
7492  insides_dirty = true;
7493  pivot_dirty = true;
7494 
7495  // destroyed parts lose any contained fuels, battery charges or ammo
7496  leak_fuel( vp );
7497 
7498  for( const item &e : vp.items ) {
7499  here.add_item_or_charges( vppos, e );
7500  }
7501  vp.items.clear();
7502 
7503  invalidate_mass();
7504  coeff_air_changed = true;
7505 
7506  // refresh cache in case the broken part has changed the status
7507  // do not remove fakes parts in case external vehicle part references get invalidated
7508  refresh( false );
7509  }
7510 
7511  if( vp.is_fuel_store() ) {
7512  explode_fuel( vp, type );
7513  } else if( vp.is_broken() && vpi.has_flag( "UNMOUNT_ON_DAMAGE" ) ) {
7514  const int vp_idx = index_of_part( &vp, /* include_removed = */ true );
7515  monster *mon = get_monster( vp_idx );
7516  if( mon != nullptr && mon->has_effect( effect_harnessed ) ) {
7518  }
7519  if( vpi.has_flag( "TOW_CABLE" ) ) {
7520  invalidate_towing( true );
7521  } else {
7522  item part_as_item = part_to_item( vp );
7523  add_msg_if_player_sees( vppos, m_bad, _( "The %1$s's %2$s is disconnected!" ), name, vp.name() );
7524  if( vpi.has_flag( VPFLAG_POWER_TRANSFER ) ) {
7525  remove_remote_part( vp );
7526  part_as_item.set_damage( 0 );
7527  } else {
7528  part_as_item.set_damage( vpi.base_item.obj().damage_max() - 1 );
7529  }
7530  if( !magic ) {
7531  here.add_item_or_charges( vppos, part_as_item );
7532  }
7533  if( !g || &get_map() != &here ) {
7534  MapgenRemovePartHandler handler( here );
7535  remove_part( vp, handler );
7536  } else {
7537  remove_part( vp );
7538  }
7539  }
7540  }
7541 
7542  return std::max( dres, 0 );
7543 }
bool remove_effect(const efftype_id &eff_id, const bodypart_id &bp)
Removes a listed effect.
Definition: creature.cpp:1722
COLONY_FORCE_INLINE void clear() noexcept
Empties the colony and removes all elements and groups.
Definition: colony.h:2408
void set_damage(int qty)
Sets item damage constrained by [degradation and max_damage].
Definition: item.cpp:905
void memory_cache_dec_set_dirty(const tripoint &p, bool value) const
Definition: map.cpp:336
const T & obj() const
Returns the actual object this id refers to.
Definition: achievement.cpp:71
void leak_fuel(vehicle_part &pt) const
empty the contents of a tank, battery or turret spilling liquids randomly on the ground
Definition: vehicle.cpp:7545
int break_off(map &here, vehicle_part &vp, int dmg)
Definition: vehicle.cpp:7311
bool insides_dirty
Definition: vehicle.h:2367
bool pivot_dirty
Definition: vehicle.h:2320
bool coeff_air_changed
Definition: vehicle.h:2332
void stop_autodriving(bool apply_brakes=true)
std::vector< int > rotors
Definition: vehicle.h:2184
void set_flyable(bool val)
Definition: vehicle.cpp:4402
bool mod_hp(vehicle_part &pt, int qty)
Apply damage to part constrained by range [0,durability] possibly destroying it.
bool is_autodriving
Definition: vehicle.h:2347
bool is_flyable() const
Definition: vehicle.cpp:4397
bool explode_fuel(vehicle_part &vp, const damage_type_id &type)
Definition: vehicle.cpp:7430
itype_id base_item
base item for this part
Definition: veh_type.h:400
int damage_max() const
Definition: itype.h:1471
bool is_fuel_store(bool skip_broke=true) const
Can this part store fuel of any type @skip_broke exclude broken parts.
int hp() const
current part health with range [0,durability]
@ VPFLAG_SIMPLE_PART
Definition: veh_type.h:74
static const damage_type_id damage_pure("pure")
static const damage_type_id damage_heat("heat")

References _, map::add_item_or_charges(), add_msg_if_player_sees(), vpart_info::base_item, break_off(), cata::colony< element_type, element_allocator_type, element_skipfield_type >::clear(), coeff_air_changed, damage_heat, itype::damage_max(), damage_pure, vpart_info::damage_reduction, vpart_info::durability, effect_harnessed, explode_fuel(), g, get_map(), get_monster(), global_part_pos3(), Creature::has_effect(), vpart_info::has_flag(), vehicle_part::hp(), index_of_part(), vehicle_part::info(), insides_dirty, invalidate_mass(), invalidate_towing(), is_autodriving, vehicle_part::is_broken(), is_flyable(), vehicle_part::is_fuel_store(), vehicle_part::items, leak_fuel(), m_bad, magic, max(), map::memory_cache_dec_set_dirty(), min(), mod_hp(), vehicle_part::name(), name, string_id< T >::obj(), part_to_item(), pivot_dirty, refresh(), Creature::remove_effect(), remove_part(), remove_remote_part(), vehicle_part::removed, rotors, item::set_damage(), set_flyable(), stop_autodriving(), type, VPFLAG_POWER_TRANSFER, and VPFLAG_SIMPLE_PART.

Referenced by damage(), damage_all(), do_engine_damage(), handle_trap(), smash_security_system(), and thrust().

◆ decrement_summon_timer()

bool vehicle::decrement_summon_timer ( )

Definition at line 6111 of file vehicle.cpp.

6112 {
6113  if( !summon_time_limit ) {
6114  return false;
6115  }
6116  if( *summon_time_limit <= 0_turns ) {
6117  map &here = get_map();
6118  for( const vpart_reference &vpr : get_all_parts() ) {
6119  vehicle_part &vp = vpr.part();
6120  const tripoint_bub_ms pos = bub_part_pos( vp );
6121  for( item &it : vp.items ) {
6122  here.add_item_or_charges( pos, it );
6123  }
6124  vp.items.clear();
6125  }
6126  add_msg_if_player_sees( global_pos3(), m_info, _( "Your %s winks out of existence." ), name );
6127  get_map().destroy_vehicle( this );
6128  return true;
6129  } else {
6130  *summon_time_limit -= 1_turns;
6131  }
6132  return false;
6133 }
std::optional< time_duration > summon_time_limit
Definition: vehicle.h:2221

References _, map::add_item_or_charges(), add_msg_if_player_sees(), bub_part_pos(), cata::colony< element_type, element_allocator_type, element_skipfield_type >::clear(), map::destroy_vehicle(), get_all_parts(), get_map(), global_pos3(), vehicle_part::items, m_info, name, pos, and summon_time_limit.

Referenced by act_on_map().

◆ deserialize()

void vehicle::deserialize ( const JsonObject data)

Definition at line 3359 of file savegame_json.cpp.

3360 {
3361  data.allow_omitted_members();
3362 
3363  int fdir = 0;
3364  int mdir = 0;
3365 
3366  data.read( "type", type );
3367  data.read( "posx", pos.x );
3368  data.read( "posy", pos.y );
3369  data.read( "om_id", om_id );
3370  data.read( "faceDir", fdir );
3371  data.read( "moveDir", mdir );
3372  int turn_dir_int;
3373  data.read( "turn_dir", turn_dir_int );
3374  turn_dir = units::from_degrees( turn_dir_int );
3375  data.read( "last_turn", turn_dir_int );
3376  last_turn = units::from_degrees( turn_dir_int );
3377  data.read( "velocity", velocity );
3378  data.read( "avg_velocity", avg_velocity );
3379  data.read( "falling", is_falling );
3380  if( !data.read( "in_deep_water", in_deep_water ) ) {
3381  // fallback; remove after 0.I
3382  data.read( "floating", in_deep_water );
3383  }
3384  data.read( "in_water", in_water );
3385  data.read( "flying", is_flying );
3386  data.read( "cruise_velocity", cruise_velocity );
3387  data.read( "vertical_velocity", vertical_velocity );
3388  data.read( "engine_on", engine_on );
3389  data.read( "tracking_on", tracking_on );
3390  data.read( "skidding", skidding );
3391  data.read( "of_turn_carry", of_turn_carry );
3392  data.read( "is_locked", is_locked );
3393  data.read( "is_alarm_on", is_alarm_on );
3394  data.read( "camera_on", camera_on );
3395  data.read( "autopilot_on", autopilot_on );
3396  data.read( "precollision_on", precollision_on );
3397  data.read( "last_update_turn", last_update );
3398 
3399  units::angle fdir_angle = units::from_degrees( fdir );
3400  face.init( fdir_angle );
3401  move.init( units::from_degrees( mdir ) );
3402  data.read( "name", name );
3403  std::string temp_id;
3404  std::string temp_old_id;
3405  data.read( "owner", temp_id );
3406  data.read( "old_owner", temp_old_id );
3407  owner = faction_id( temp_id );
3408  old_owner = faction_id( temp_old_id );
3409  data.read( "theft_time", theft_time );
3410 
3411  deserialize_parts( data.get_array( "parts" ) );
3412 
3413  // we persist the pivot anchor so that if the rules for finding
3414  // the pivot change, existing vehicles do not shift around.
3415  // Loading vehicles that predate the pivot logic is a special
3416  // case of this, they will load with an anchor of (0,0) which
3417  // is what they're expecting.
3418  data.read( "pivot", pivot_anchor[0] );
3419  pivot_anchor[1] = pivot_anchor[0];
3420  pivot_rotation[1] = pivot_rotation[0] = fdir_angle;
3421  data.read( "is_on_ramp", is_on_ramp );
3422  data.read( "is_autodriving", is_autodriving );
3423  data.read( "is_following", is_following );
3424  data.read( "is_patrolling", is_patrolling );
3425  data.read( "autodrive_local_target", autodrive_local_target );
3426  data.read( "airworthy", flyable );
3427  data.read( "requested_z_change", requested_z_change );
3428  data.read( "summon_time_limit", summon_time_limit );
3429  data.read( "magic", magic );
3430 
3431  smart_controller_cfg = std::nullopt;
3432  data.read( "smart_controller", smart_controller_cfg );
3433  data.read( "vehicle_noise", vehicle_noise );
3434  data.read( "tags", tags );
3435  data.read( "labels", labels );
3436  data.read( "fuel_remainder", fuel_remainder );
3437  data.read( "fuel_used_last_turn", fuel_used_last_turn );
3438 
3439  refresh();
3440 
3441  point p;
3442  zone_data zd;
3443  for( JsonObject sdata : data.get_array( "zones" ) ) {
3444  sdata.allow_omitted_members();
3445  sdata.read( "point", p );
3446  sdata.read( "zone", zd );
3447  loot_zones.emplace( p, zd );
3448  }
3449  data.read( "other_tow_point", tow_data.other_towing_point );
3450  // Note that it's possible for a vehicle to be loaded midway
3451  // through a turn if the player is driving REALLY fast and their
3452  // own vehicle motion takes them in range. An undefined value for
3453  // on_turn caused occasional weirdness if the undefined value
3454  // happened to be positive.
3455  //
3456  // Setting it to zero means it won't get to move until the start
3457  // of the next turn, which is what happens anyway if it gets
3458  // loaded anywhere but midway through a driving cycle.
3459  //
3460  // Something similar to vehicle::gain_moves() would be ideal, but
3461  // that can't be used as it currently stands because it would also
3462  // make it instantly fire all its turrets upon load.
3463  of_turn = 0;
3464 }
bool read(std::string_view name, T &t, bool throw_on_error=true) const
JsonArray get_array(std::string_view key) const
void allow_omitted_members() const
tripoint other_towing_point
Definition: vehicle.h:214
std::optional< time_point > theft_time
Definition: vehicle.h:2300
faction_id old_owner
Definition: vehicle.h:2104
int avg_velocity
vehicle continuous moving average velocity see https://en.wikipedia.org/wiki/Moving_average#Exponenti...
Definition: vehicle.h:2282
bool flyable
Definition: vehicle.h:2341
bool is_on_ramp
Definition: vehicle.h:2345
units::angle last_turn
Definition: vehicle.h:2293
towing_data tow_data
Definition: vehicle.h:2308
std::set< label > labels
Definition: vehicle.h:2210
void deserialize_parts(const JsonArray &data)
std::unordered_multimap< point, zone_data > loot_zones
Definition: vehicle.h:2216
time_point last_update
Definition: vehicle.h:2266
bool precollision_on
Definition: vehicle.h:2361
int om_id
Definition: vehicle.h:2288
unsigned char vehicle_noise
Definition: vehicle.h:2374
faction_id owner
Definition: vehicle.h:2102
These are zones the player can designate.
Definition: clzones.h:349
constexpr quantity< double, angle_in_radians_tag > from_degrees(const value_type v)
Definition: units.h:752

References item_pocket::data, faction_id, units::from_degrees(), move, om_direction::name(), math_opers::pos(), catacurses::refresh(), anonymous_namespace{item_tname.cpp}::tags(), and type.

◆ deserialize_parts()

void vehicle::deserialize_parts ( const JsonArray data)

Definition at line 3466 of file savegame_json.cpp.

3467 {
3468  parts.clear();
3469  parts.reserve( data.size() );
3470  for( const JsonValue jv : data ) {
3471  try {
3473  jv.read( part, /* throw_on_error = */ true );
3474  parts.emplace_back( std::move( part ) );
3475  } catch( const JsonError &err ) {
3476  debugmsg( err.what() );
3477  }
3478  }
3479 }
size_t size() const

References item_pocket::data, and debugmsg.

Referenced by restore_folded_parts().

◆ dir_vec()

rl_vec2d vehicle::dir_vec ( ) const

Definition at line 1618 of file vehicle_move.cpp.

1619 {
1620  return angle_to_vec( turn_dir );
1621 }
static rl_vec2d angle_to_vec(const units::angle &angle)

References angle_to_vec(), and turn_dir.

Referenced by game::get_veh_dir_indicator_location(), handling_difficulty(), and MapExtras::mx_helicopter().

◆ disable_smart_controller_if_needed()

void vehicle::disable_smart_controller_if_needed ( )

Definition at line 5796 of file vehicle.cpp.

5797 {
5798  const auto get_force_smart_controller_off_when_engine_stop = [] {
5799  std::string force_stop_option = get_option<std::string>( "FORCE_SMART_CONTROLLER_OFF_ON_ENGINE_STOP" );
5800  if( force_stop_option == "enabled" )
5801  {
5802  return true;
5803  }
5804  if( force_stop_option == "disabled" )
5805  {
5806  return false;
5807  }
5808  if( force_stop_option != "ask" )
5809  {
5810  debugmsg( "Unexpected option \"%s\" for \"FORCE_SMART_CONTROLLER_OFF_ON_ENGINE_STOP\"",
5811  force_stop_option );
5812  }
5813  return query_yn( _( "Smart controller engine may turn on engine back. Disable it?" ) );
5814  };
5815 
5817  get_force_smart_controller_off_when_engine_stop() ) {
5818  for( const vpart_reference &vp : get_avail_parts( "SMART_ENGINE_CONTROLLER" ) ) {
5819  vp.part().enabled = false;
5820  add_msg( _( "Turned off %s." ), vp.part().name() );
5821  }
5822  }
5823 }
bool has_available_electric_engine()
Definition: vehicle.cpp:5785
bool query_yn(const std::string &text)
Definition: output.cpp:811

References _, add_msg(), debugmsg, get_avail_parts(), has_available_electric_engine(), has_enabled_smart_controller, and query_yn().

Referenced by build_interact_menu().

◆ discharge_battery()

int vehicle::discharge_battery ( int  amount,
bool  apply_loss = true 
)

Discharges batteries in connected vehicles/appliances.

Parameters
amountto discharge in kJ
apply_lossif true apply wire loss when charge crosses vehicle power cables
Returns
0 or unfulfilled part of amount in kJ

Definition at line 5564 of file vehicle.cpp.

5565 {
5566  if( amount < 0 ) {
5567  debugmsg( "called vehicle::discharge_battery(%d), potential bug", amount );
5568  return amount;
5569  }
5570  if( amount == 0 ) {
5571  return 0;
5572  }
5573  const std::map<vpart_reference, float> batteries = search_connected_batteries();
5574  if( batteries.empty() ) {
5575  return amount;
5576  }
5577  const double loss = apply_loss ? weighted_power_loss( batteries ) : 0.0;
5578  int64_t total_charge = 0; // sum of current charge of all batteries
5579  int64_t total_capacity = 0; // sum of capacity of all batteries
5580  for( const std::pair<const vpart_reference, float> &pair : batteries ) {
5581  vehicle_part &vp = pair.first.part();
5582  total_charge += vp.ammo_remaining();
5583  total_capacity += vp.ammo_capacity( ammo_battery );
5584  }
5585 
5586  int64_t discharged = amount;
5587  int64_t lost_amount = roll_remainder( amount * loss );
5588  int64_t lossy_amount = amount + lost_amount;
5589  if( lossy_amount > total_charge ) { // not enough available, recalculate loss
5590  lossy_amount = total_charge; // cap at the maximum possible discharge
5591  lost_amount = roll_remainder( lossy_amount * loss );
5592  discharged = lossy_amount - lost_amount;
5593  }
5594  total_charge -= lossy_amount;
5595  const int tried_discharging = amount;
5596  amount -= discharged;
5597 
5598  distribute_charge_evenly( batteries, total_charge, total_capacity );
5599 
5601  "batteries: %d, loss: %.3f, tried discharging: %d kJ, actual discharged: %d kJ, usable: %d kJ, lost: %d kJ, missing: %d kJ",
5602  batteries.size(), loss, tried_discharging, lossy_amount, discharged, lost_amount,
5603  amount );
5604 
5605  return amount; // non zero if batteries couldn't provide the entire amount
5606 }

References add_msg_debug, ammo_battery, vehicle_part::ammo_capacity(), vehicle_part::ammo_remaining(), batteries, debugmsg, debugmode::DF_VEHICLE, distribute_charge_evenly(), roll_remainder(), search_connected_batteries(), and weighted_power_loss().

Referenced by item::ammo_consume(), Character::burn_fuel(), item::charge_linked_batteries(), drain(), power_parts(), process_vehicle_items(), spell_effect::recharge_vehicle(), start_engine(), update_time(), use_vehicle_tool(), and debug_menu::vehicle_battery_charge().

◆ disp_name()

std::string vehicle::disp_name ( ) const

◆ do_autodrive()

autodrive_result vehicle::do_autodrive ( Character driver)

Definition at line 1347 of file vehicle_autodrive.cpp.

1348 {
1349  if( !is_autodriving ) {
1350  return autodrive_result::abort;
1351  }
1352  if( !player_in_control( driver ) || skidding ) {
1353  driver.add_msg_if_player( m_warning, _( "You lose control as the vehicle starts skidding." ) );
1354  stop_autodriving( false );
1355  return autodrive_result::abort;
1356  }
1357  const tripoint_abs_ms veh_pos = global_square_location();
1358  const tripoint_abs_omt veh_omt = project_to<coords::omt>( veh_pos );
1359  std::vector<tripoint_abs_omt> &omt_path = driver.omt_path;
1360  while( !omt_path.empty() && veh_omt.xy() == omt_path.back().xy() ) {
1361  omt_path.pop_back();
1362  }
1363  if( omt_path.empty() ) {
1364  stop_autodriving( false );
1366  }
1368  active_autodrive_controller = std::make_shared<autodrive_controller>( *this, driver );
1369  }
1370  if( &active_autodrive_controller->get_driver() != &driver ) {
1371  debugmsg( "Driver changed while auto-driving" );
1372  stop_autodriving();
1373  return autodrive_result::abort;
1374  }
1375  active_autodrive_controller->check_safe_speed();
1376  std::optional<navigation_step> next_step = active_autodrive_controller->compute_next_step();
1377  if( !next_step ) {
1378  // message handles pathfinding failure either due to obstacles or inability to see
1379  driver.add_msg_if_player( _( "Can't see a path forward." ) );
1380  stop_autodriving( false );
1381  return autodrive_result::abort;
1382  }
1383  if( next_step->pos.xy() != veh_pos.xy() ) {
1384  debugmsg( "compute_next_step returned an invalid result" );
1385  stop_autodriving();
1386  return autodrive_result::abort;
1387  }
1388  if( next_step->target_speed_tps == 0 && velocity == 0 ) {
1389  stop_autodriving( false );
1391  }
1392  cruise_velocity = next_step->target_speed_tps * VMIPH_PER_TPS;
1393 
1394  // check for collisions before we steer, since steering may end our turn
1395  // which would cause the vehicle to move and maybe crash
1396  switch( active_autodrive_controller->check_collision_zone( next_step->steering_dir ) ) {
1398  driver.add_msg_if_player( m_warning, _( "You can't see anything in front of your vehicle!" ) );
1399  stop_autodriving();
1400  return autodrive_result::abort;
1402  driver.add_msg_if_player( m_warning, _( "You're about to crash into something!" ) );
1403  stop_autodriving( false );
1404  return autodrive_result::abort;
1406  active_autodrive_controller->reduce_speed();
1407  if( cruise_velocity > VMIPH_PER_TPS ) {
1409  }
1410  break;
1412  break;
1413  }
1414 
1415  int turn_delta = orientation_diff( next_step->steering_dir, to_orientation( turn_dir ) );
1416  // pldrive() does not handle steering multiple times in one call correctly
1417  // call it multiple times, matching how a player controls the vehicle
1418  for( int i = 0; i < std::abs( turn_delta ); i++ ) {
1419  if( driver.get_moves() <= 0 ) {
1420  // we couldn't steer as many times as we wanted to but there's
1421  // nothing we can do about it now, hope we don't crash!
1422  break;
1423  }
1424  pldrive( driver, { signum( turn_delta ), 0 } );
1425  }
1426  // Don't do anything else below; the driver's turn may be over (moves <= 0) so
1427  // any extra actions would be "cheating".
1428 
1429  return autodrive_result::ok;
1430 }
std::vector< tripoint_abs_omt > omt_path
Definition: character.h:1703
int get_moves() const
Definition: creature.cpp:2004
constexpr auto xy() const
Definition: coordinates.h:273
std::shared_ptr< autodrive_controller > active_autodrive_controller
Definition: vehicle.h:2245
void pldrive(Character &driver, const point &p, int z=0)
Player is driving the vehicle.
static constexpr int VMIPH_PER_TPS
static int signum(int val)
static int orientation_diff(const orientation &dir1, const orientation &dir2)
static orientation to_orientation(units::angle angle)

References _, abort, abs(), active_autodrive_controller, Character::add_msg_if_player(), close_obstacle, cruise_velocity, debugmsg, finished, Creature::get_moves(), global_square_location(), is_autodriving, m_warning, no_visibility, ok, Character::omt_path, orientation_diff(), player_in_control(), pldrive(), signum(), skidding, slow_down, stop_autodriving(), to_orientation(), turn_dir, velocity, VMIPH_PER_TPS, and coords::coord_point< Point, Origin, Scale, InBounds >::xy().

Referenced by autodrive_activity_actor::do_turn().

◆ do_engine_damage()

void vehicle::do_engine_damage ( vehicle_part vp,
int  strain 
)

Definition at line 5608 of file vehicle.cpp.

5609 {
5610  strain = std::min( 25, strain );
5611  if( is_engine_on( vp ) && !is_perpetual_type( vp ) && engine_fuel_left( vp ) &&
5612  rng( 1, 100 ) < strain ) {
5613  const int dmg = rng( 0, strain * 4 );
5614  damage_direct( get_map(), vp, dmg );
5615  if( one_in( 2 ) ) {
5616  add_msg( _( "Your engine emits a high pitched whine." ) );
5617  } else {
5618  add_msg( _( "Your engine emits a loud grinding sound." ) );
5619  }
5620  }
5621 }
bool is_engine_on(const vehicle_part &vp) const
Definition: vehicle.cpp:1015

References _, add_msg(), damage_direct(), engine_fuel_left(), get_map(), is_engine_on(), is_perpetual_type(), min(), one_in(), rng(), and strain().

Referenced by thrust().

◆ do_environmental_effects()

bool vehicle::do_environmental_effects ( ) const
private

Definition at line 3983 of file vehicle.cpp.

3984 {
3985  bool needed = false;
3986  map &here = get_map();
3987  // check for smoking parts
3988  for( const vpart_reference &vp : get_all_parts() ) {
3989  /* Only lower blood level if:
3990  * - The part is outside.
3991  * - The weather is any effect that would cause the player to be wet. */
3992  if( vp.part().blood > 0 && here.is_outside( vp.pos() ) ) {
3993  needed = true;
3994  if( get_weather().weather_id->rains &&
3995  get_weather().weather_id->precip != precip_class::very_light ) {
3996  vp.part().blood--;
3997  }
3998  }
3999  }
4000  return needed;
4001 }
bool is_outside(const tripoint &p) const
Definition: map.cpp:3395
weather_manager & get_weather()
Definition: game.cpp:13866

References get_all_parts(), get_map(), get_weather(), map::is_outside(), and very_light.

Referenced by gain_moves().

◆ do_remove_part_actual()

bool vehicle::do_remove_part_actual ( )

Definition at line 2105 of file vehicle.cpp.

2106 {
2107  bool changed = false;
2108  map &here = get_map();
2109  for( std::vector<vehicle_part>::iterator it = parts.end(); it != parts.begin(); /*noop*/ ) {
2110  --it;
2111  vehicle_part &vp = *it;
2112  if( vp.removed || vp.is_fake ) {
2113  // We are first stripping out removed parts and marking
2114  // their corresponding real parts as "not fake" so they are regenerated,
2115  // and then removing any parts that have been marked as removed.
2116  // This is assured by iterating from the end to the beginning as
2117  // fake parts are always at the end of the parts vector.
2118  if( vp.is_fake ) {
2119  parts[vp.fake_part_to].has_fake = false;
2120  } else {
2121  get_items( vp ).clear();
2122  }
2123  if( vp.is_real_or_active_fake() ) {
2124  const tripoint pt = global_part_pos3( vp );
2125  here.clear_vehicle_point_from_cache( this, pt );
2126  }
2127  it = parts.erase( it );
2128  changed = true;
2129  }
2130  }
2131  return changed;
2132 }
virtual void clear()
Definition: item_stack.cpp:24
int fake_part_to
Definition: vehicle.h:573

References item_stack::clear(), map::clear_vehicle_point_from_cache(), vehicle_part::fake_part_to, get_items(), get_map(), global_part_pos3(), vehicle_part::is_fake, vehicle_part::is_real_or_active_fake(), parts, and vehicle_part::removed.

Referenced by part_removal_cleanup(), and remove_fake_parts().

◆ do_towing_move()

void vehicle::do_towing_move ( )

Definition at line 6656 of file vehicle.cpp.

6657 {
6658  if( !no_towing_slack() || velocity <= 0 ) {
6659  return;
6660  }
6661  bool invalidate = false;
6662  const int tow_index = get_tow_part();
6663  if( tow_index == -1 ) {
6664  debugmsg( "tried to do towing move, but no tow part" );
6665  invalidate = true;
6666  }
6667  vehicle *towed_veh = tow_data.get_towed();
6668  if( !towed_veh ) {
6669  debugmsg( "tried to do towing move, but towed vehicle doesn't exist." );
6671  return;
6672  }
6673  const int other_tow_index = towed_veh->get_tow_part();
6674  if( other_tow_index == -1 ) {
6675  debugmsg( "tried to do towing move but towed vehicle has no towing part" );
6676  invalidate = true;
6677  }
6678  if( towed_veh->global_pos3().z != global_pos3().z ) {
6679  // how the hellicopter did this happen?
6680  // yes, this can happen when towing over a bridge (see #47293)
6681  invalidate = true;
6682  add_msg( m_info, _( "A towing cable snaps off of %s." ), towed_veh->disp_name() );
6683  }
6684  if( invalidate ) {
6685  invalidate_towing( true );
6686  return;
6687  }
6688  map &here = get_map();
6689  const tripoint tower_tow_point = here.getabs( global_part_pos3( tow_index ) );
6690  const tripoint towed_tow_point = here.getabs( towed_veh->global_part_pos3( other_tow_index ) );
6691  // same as above, but where the pulling vehicle is pulling from
6692  units::angle towing_veh_angle = towed_veh->get_angle_from_targ( tower_tow_point );
6693  const bool reverse = towed_veh->tow_data.tow_direction == TOW_BACK;
6694  int accel_y = 0;
6695  tripoint vehpos = global_square_location().raw();
6696  int turn_x = get_turn_from_angle( towing_veh_angle, vehpos, tower_tow_point, reverse );
6697  if( rl_dist( towed_tow_point, tower_tow_point ) < 6 ) {
6698  accel_y = reverse ? -1 : 1;
6699  }
6700  if( towed_veh->velocity <= velocity && rl_dist( towed_tow_point, tower_tow_point ) >= 7 ) {
6701  accel_y = reverse ? 1 : -1;
6702  }
6703  if( rl_dist( towed_tow_point, tower_tow_point ) >= 12 ) {
6704  towed_veh->velocity = velocity * 1.8;
6705  if( reverse ) {
6706  towed_veh->velocity = -towed_veh->velocity;
6707  }
6708  } else {
6709  towed_veh->velocity = reverse ? -velocity : velocity;
6710  }
6711  if( towed_veh->tow_data.tow_direction == TOW_FRONT ) {
6712  towed_veh->selfdrive( point( turn_x, accel_y ) );
6713  } else if( towed_veh->tow_data.tow_direction == TOW_BACK ) {
6714  accel_y = 10;
6715  towed_veh->selfdrive( point( turn_x, accel_y ) );
6716  } else {
6717  towed_veh->skidding = true;
6718  std::vector<tripoint> lineto = line_to( here.getlocal( towed_tow_point ),
6719  here.getlocal( tower_tow_point ) );
6720  tripoint nearby_destination;
6721  if( lineto.size() >= 2 ) {
6722  nearby_destination = lineto[1];
6723  } else {
6724  nearby_destination = tower_tow_point;
6725  }
6726  const tripoint destination_delta( here.getlocal( tower_tow_point ).xy() - nearby_destination.xy() +
6727  tripoint( 0, 0, towed_veh->global_pos3().z ) );
6728  const tripoint move_destination( clamp( destination_delta.x, -1, 1 ),
6729  clamp( destination_delta.y, -1, 1 ),
6730  clamp( destination_delta.z, -1, 1 ) );
6731  here.move_vehicle( *towed_veh, move_destination, towed_veh->face );
6732  towed_veh->move = tileray( destination_delta.xy() );
6733  }
6734 
6735 }
constexpr T clamp(const T &val, const T &min, const T &max)
Clamp first argument so that it is no lower than second and no higher than third.
Definition: cata_utility.h:221
tripoint getabs(const tripoint &p) const
Translates local (to this map) coordinates of a square to global absolute coordinates.
Definition: map.cpp:9614
vehicle * get_towed() const
Definition: vehicle.h:205
towing_point_side tow_direction
Definition: vehicle.h:212
units::angle get_angle_from_targ(const tripoint &targ) const
Definition: vehicle.cpp:843
bool no_towing_slack() const
Definition: vehicle.cpp:6919
void selfdrive(const point &)
vehicle is driving itself
std::string disp_name() const
int get_tow_part() const
Definition: vehicle.cpp:6782
std::vector< coords::coord_point< Point, Origin, Scale, LhsInBounds &&RhsInBounds > > line_to(const coords::coord_point< Point, Origin, Scale, LhsInBounds > &loc1, const coords::coord_point< Point, Origin, Scale, RhsInBounds > &loc2)
Definition: coordinates.h:798
void invalidate(const rectangle< point > &rect, const bool reenable_uis_below)
Invalidate a portion of the screen when a UI is resized, closed, etc.
Definition: ui_manager.cpp:499
static int get_turn_from_angle(const units::angle &angle, const tripoint &vehpos, const tripoint &target, bool reverse=false)
Definition: vehicle.cpp:707
@ TOW_FRONT
Definition: vehicle.h:187
@ TOW_BACK
Definition: vehicle.h:189

References _, add_msg(), clamp(), debugmsg, disp_name(), face, get_angle_from_targ(), get_map(), get_tow_part(), towing_data::get_towed(), get_turn_from_angle(), map::getabs(), map::getlocal(), global_part_pos3(), global_pos3(), global_square_location(), ui_manager::invalidate(), invalidate_towing(), line_to(), m_info, move, map::move_vehicle(), no_towing_slack(), point, coords::coord_point_mut< Point, Subpoint, InBounds >::raw(), rl_dist(), selfdrive(), skidding, TOW_BACK, tow_data, towing_data::tow_direction, TOW_FRONT, velocity, tripoint::x, tripoint::xy(), tripoint::y, and tripoint::z.

Referenced by map::move_vehicle().

◆ drain() [1/2]

int vehicle::drain ( const itype_id ftype,
int  amount,
const std::function< bool(vehicle_part &)> &  filter = return_truevehicle_part &>,
bool  apply_loss = true 
)

Definition at line 3604 of file vehicle.cpp.

3607 {
3608  if( ftype == fuel_type_battery ) {
3609  // Batteries get special handling to take advantage of jumper
3610  // cables -- discharge_battery knows how to recurse properly
3611  // (including taking cable power loss into account).
3612  int remnant = discharge_battery( amount, apply_loss );
3613 
3614  // discharge_battery returns amount of charges that were not
3615  // found anywhere in the power network, whereas this function
3616  // returns amount of charges consumed; simple subtraction.
3617  return amount - remnant;
3618  }
3619 
3620  int drained = 0;
3621  for( vehicle_part &p : parts ) {
3622  if( !filter( p ) ) {
3623  continue;
3624  }
3625  if( amount <= 0 ) {
3626  break;
3627  }
3628  if( p.ammo_current() == ftype ) {
3629  int qty = p.ammo_consume( amount, global_part_pos3( p ) );
3630  drained += qty;
3631  amount -= qty;
3632  }
3633  }
3634 
3635  invalidate_mass();
3636  return drained;
3637 }

References discharge_battery(), filter, fuel_type_battery, global_part_pos3(), invalidate_mass(), and parts.

Referenced by act_vehicle_siphon(), act_vehicle_unload_fuel(), veh_interact::do_siphon(), drain(), turret_data::post_fire(), veh_app_interact::siphon(), use_autoclave(), use_dishwasher(), use_vehicle_tool(), and use_washing_machine().

◆ drain() [2/2]

int vehicle::drain ( int  index,
int  amount,
bool  apply_loss = true 
)

Definition at line 3639 of file vehicle.cpp.

3640 {
3641  if( index < 0 || index >= static_cast<int>( parts.size() ) ) {
3642  debugmsg( "Tried to drain an invalid part index: %d", index );
3643  return 0;
3644  }
3645  vehicle_part &pt = parts[index];
3646  if( pt.ammo_current() == fuel_type_battery ) {
3647  //return_true< vehicle_part &> is needed because apply_loss needs to be last arg
3648  //to not break existing code, but C++ requires you also invoke all optional
3649  //arguments to the left of any invoked. make sure to change this if the default for
3650  //filters in the function above ever changes
3651  return drain( fuel_type_battery, amount, return_true< vehicle_part &>, apply_loss );
3652  }
3653  if( !pt.is_tank() || !pt.ammo_remaining() ) {
3654  debugmsg( "Tried to drain something without any liquid: %s amount: %d ammo: %d",
3655  pt.name(), amount, pt.ammo_remaining() );
3656  return 0;
3657  }
3658 
3659  const int drained = pt.ammo_consume( amount, global_part_pos3( pt ) );
3660  invalidate_mass();
3661  return drained;
3662 }
int drain(const itype_id &ftype, int amount, const std::function< bool(vehicle_part &)> &filter=return_true< vehicle_part & >, bool apply_loss=true)
Definition: vehicle.cpp:3604
bool is_tank() const
Can this part contain liquid fuels?
int ammo_consume(int qty, const tripoint &pos)
Consume fuel, charges or ammunition (if available)

References vehicle_part::ammo_consume(), vehicle_part::ammo_current(), vehicle_part::ammo_remaining(), debugmsg, drain(), fuel_type_battery, global_part_pos3(), invalidate_mass(), vehicle_part::is_tank(), vehicle_part::name(), and parts.

◆ drain_energy()

units::energy vehicle::drain_energy ( const itype_id ftype,
units::energy  wanted_energy 
)

Consumes enough fuel by energy content.

Does not support cable draining.

Parameters
ftypeType of fuel
wanted_energyDesired amount of energy of fuel to consume
Returns
Amount of energy actually consumed. May be more or less than energy.

Definition at line 4847 of file vehicle.cpp.

4848 {
4849  units::energy drained = 0_J;
4850  for( vehicle_part &p : parts ) {
4851  if( wanted_energy <= 0_J ) {
4852  break;
4853  }
4854 
4855  units::energy consumed = p.consume_energy( ftype, wanted_energy );
4856  drained += consumed;
4857  wanted_energy -= consumed;
4858  }
4859 
4860  invalidate_mass();
4861  return drained;
4862 }

References invalidate_mass(), and parts.

Referenced by consume_fuel().

◆ drive_to_local_target()

void vehicle::drive_to_local_target ( const tripoint target,
bool  follow_protocol 
)

Definition at line 730 of file vehicle.cpp.

731 {
732  Character &player_character = get_player_character();
733  if( follow_protocol && player_character.in_vehicle ) {
735  string_format( _( "the %s emitting a beep and saying \"Autonomous driving protocols suspended!\"" ),
736  name ) );
738  return;
739  }
740  refresh();
741  map &here = get_map();
742  tripoint vehpos = global_square_location().raw();
744 
745  bool stop = precollision_check( angle, here, follow_protocol );
746  if( stop ) {
747  if( autopilot_on ) {
749  string_format( _( "the %s emitting a beep and saying \"Obstacle detected!\"" ),
750  name ) );
751  }
753  return;
754  }
755  int turn_x = get_turn_from_angle( angle, vehpos, target );
756  int accel_y = 0;
757  // best to cruise around at a safe velocity or 40mph, whichever is lowest
758  // accelerate when it doesn't need to turn.
759  // when following player, take distance to player into account.
760  // we really want to avoid running the player over.
761  // If its a helicopter, we dont need to worry about airborne obstacles so much
762  // And fuel efficiency is terrible at low speeds.
763  const int safe_player_follow_speed = 400 *
764  player_character.current_movement_mode()->move_speed_mult();
765  if( follow_protocol ) {
766  if( ( ( turn_x > 0 || turn_x < 0 ) && velocity > safe_player_follow_speed ) ||
767  rl_dist( vehpos, here.getabs( player_character.pos() ) ) < 7 + ( ( mount_max.y * 3 ) + 4 ) ) {
768  accel_y = 1;
769  }
770  if( ( velocity < std::min( safe_velocity(), safe_player_follow_speed ) && turn_x == 0 &&
771  rl_dist( vehpos, here.getabs( player_character.pos() ) ) > 8 + ( ( mount_max.y * 3 ) + 4 ) ) ||
772  velocity < 100 ) {
773  accel_y = -1;
774  }
775  } else {
776  if( ( turn_x > 0 || turn_x < 0 ) && velocity > 1000 ) {
777  accel_y = 1;
778  }
780  is_flying_in_air() ? 12000 : 32 * 100 ) && turn_x == 0 ) || velocity < 500 ) {
781  accel_y = -1;
782  }
783  if( is_patrolling && velocity > 400 ) {
784  accel_y = 1;
785  }
786  }
787  selfdrive( point( turn_x, accel_y ) );
788 }
move_mode_id current_movement_mode() const
Definition: character.cpp:2159
bool in_vehicle
Definition: character.h:2693
float move_speed_mult() const
Definition: move_mode.cpp:179
bool precollision_check(units::angle &angle, map &here, bool follow_protocol)
Definition: vehicle.cpp:790
quantity< double, angle_in_radians_tag > angle
Definition: units_fwd.h:75

References _, sounds::alert, autopilot_on, Character::current_movement_mode(), get_angle_from_targ(), get_map(), get_player_character(), get_turn_from_angle(), map::getabs(), global_pos3(), global_square_location(), Character::in_vehicle, is_flying_in_air(), is_patrolling, is_rotorcraft(), min(), mount_max, move_mode::move_speed_mult(), name, point, Creature::pos(), precollision_check(), coords::coord_point_mut< Point, Subpoint, InBounds >::raw(), refresh(), rl_dist(), safe_velocity(), selfdrive(), sounds::sound(), stop(), stop_autodriving(), string_format(), velocity, and point::y.

Referenced by autopilot_patrol(), and map::vehmove().

◆ enable_patrol()

void vehicle::enable_patrol ( )

Definition at line 830 of file vehicle_use.cpp.

831 {
832  is_patrolling = true;
833  autopilot_on = true;
835  if( !engine_on ) {
836  start_engines();
837  }
838 }

References autodrive_local_target, autopilot_on, engine_on, is_patrolling, start_engines(), and tripoint_zero.

Referenced by autopilot_patrol_check().

◆ enable_refresh()

void vehicle::enable_refresh ( )

Definition at line 6148 of file vehicle.cpp.

6149 {
6150  // force all caches to recalculate
6151  no_refresh = false;
6152  mass_dirty = true;
6155  coeff_rolling_dirty = true;
6156  coeff_air_dirty = true;
6157  coeff_water_dirty = true;
6158  coeff_air_changed = true;
6159  refresh();
6160 }
bool no_refresh
Definition: vehicle.h:2317

References coeff_air_changed, coeff_air_dirty, coeff_rolling_dirty, coeff_water_dirty, mass_center_no_precalc_dirty, mass_center_precalc_dirty, mass_dirty, no_refresh, and refresh().

Referenced by vehicles::finalize_prototypes(), and remove_carried_vehicle().

◆ enclosed_at()

bool vehicle::enclosed_at ( const tripoint pos)

Definition at line 7067 of file vehicle.cpp.

7068 {
7069  refresh_insides();
7070  std::vector<vehicle_part *> parts_here = get_parts_at( pos, "BOARDABLE",
7072  if( !parts_here.empty() ) {
7073  return parts_here.front()->inside;
7074  }
7075  return false;
7076 }
void refresh_insides()
Definition: vehicle.cpp:7078

References get_parts_at(), pos, refresh_insides(), and working.

Referenced by monster::monster_move_in_vehicle(), Character::move_in_vehicle(), Character::process_effects(), monster::process_effects(), and Character::stagger().

◆ engine_cold_factor()

double vehicle::engine_cold_factor ( const vehicle_part vp) const
private

Definition at line 575 of file vehicle_use.cpp.

576 {
577  if( !vp.info().has_flag( "E_COLD_START" ) ) {
578  return 0.0;
579  }
580 
581  const tripoint pos = global_part_pos3( vp );
582  double eff_temp = units::to_fahrenheit( get_weather().get_temperature( pos ) );
583  if( !vp.has_fault_flag( "BAD_COLD_START" ) ) {
584  eff_temp = std::min( eff_temp, 20.0 );
585  }
586 
587  return 1.0 - ( std::max( 0.0, std::min( 30.0, eff_temp ) ) / 30.0 );
588 }
constexpr value_type to_fahrenheit(const quantity< value_type, temperature_in_kelvin_tag > &v)
Definition: units.h:440

References get_weather(), global_part_pos3(), vehicle_part::has_fault_flag(), vpart_info::has_flag(), vehicle_part::info(), max(), min(), pos, and units::to_fahrenheit().

Referenced by engine_start_time(), and start_engine().

◆ engine_fuel_left()

int vehicle::engine_fuel_left ( const vehicle_part vp) const

◆ engine_fuel_usage()

units::power vehicle::engine_fuel_usage ( const vehicle_part vp) const

Fuel usage for specific engine.

Parameters
eis the index of the engine in the engines array

Definition at line 4822 of file vehicle.cpp.

4823 {
4824  if( !is_engine_on( vp ) || is_perpetual_type( vp ) ) {
4825  return 0_W;
4826  }
4827  const units::power usage = vp.info().energy_consumption;
4828  if( vp.has_fault_flag( "DOUBLE_FUEL_CONSUMPTION" ) ) {
4829  return usage * 2;
4830  }
4831  return usage;
4832 }
units::power energy_consumption
Energy consumed per second by engines and motors when delivering max power Includes waste.
Definition: veh_type.h:424

References vpart_info::energy_consumption, vehicle_part::has_fault_flag(), vehicle_part::info(), is_engine_on(), and is_perpetual_type().

Referenced by fuel_usage(), and smart_controller_handle_turn().

◆ engine_start_time()

time_duration vehicle::engine_start_time ( const vehicle_part vp) const
private

Definition at line 590 of file vehicle_use.cpp.

591 {
592  time_duration result = 0_seconds;
593  if( !is_engine_on( vp ) || vp.info().has_flag( "E_STARTS_INSTANTLY" ) || !engine_fuel_left( vp ) ) {
594  return result;
595  }
596 
597  result += 1_seconds * vp.damage_percent();
598 
599  // non-linear range [100-1000]; f(0.0) = 100, f(0.6) = 250, f(0.8) = 500, f(0.9) = 1000
600  // diesel engines with working glow plugs always start with f = 0.6 (or better)
601  result += 1_seconds / tanh( 1.0 - std::min( engine_cold_factor( vp ), 0.9 ) );
602 
603  // divided by magic 16 = watts / 6000
604  const double watts_per_time = 6000;
605  const double engine_watts = units::to_watt( part_vpower_w( vp, true ) );
606  result += time_duration::from_moves( engine_watts / watts_per_time );
607  return result;
608 }
A duration defined as a number of specific time units.
Definition: calendar.h:197
static constexpr time_duration from_moves(const T t)
Definition: calendar.h:225
double engine_cold_factor(const vehicle_part &vp) const
double damage_percent() const
Current part damage as a percentage of maximum, with 0.0 being perfect condition.

References vehicle_part::damage_percent(), engine_cold_factor(), engine_fuel_left(), time_duration::from_moves(), vpart_info::has_flag(), vehicle_part::info(), is_engine_on(), min(), part_vpower_w(), and units::to_watt().

Referenced by start_engine(), and start_engines().

◆ exhaust_dest()

tripoint vehicle::exhaust_dest ( int  part) const

Definition at line 8306 of file vehicle.cpp.

8307 {
8308  point p = parts[part].mount;
8309  // Move back from engine/muffler until we find an open space
8310  while( relative_parts.find( p ) != relative_parts.end() ) {
8311  p.x += ( velocity < 0 ? 1 : -1 );
8312  }
8313  point q = coord_translate( p );
8314  return global_pos3() + tripoint( q, 0 );
8315 }
std::map< point, std::vector< int > > relative_parts
Definition: vehicle.h:2209

References coord_translate(), global_pos3(), part(), parts, relative_parts, tripoint, velocity, and point::x.

Referenced by idle(), and spew_field().

◆ explode_fuel()

bool vehicle::explode_fuel ( vehicle_part vp,
const damage_type_id type 
)
private

Definition at line 7430 of file vehicle.cpp.

7431 {
7432  const itype_id &ft = vp.info().fuel_type;
7433  item fuel = item( ft );
7434  if( !fuel.has_explosion_data() ) {
7435  return false;
7436  }
7437  const fuel_explosion_data &data = fuel.get_explosion_data();
7438 
7439  if( vp.is_broken() ) {
7440  leak_fuel( vp );
7441  }
7442 
7443  int explosion_chance = type == damage_heat ? data.explosion_chance_hot :
7444  data.explosion_chance_cold;
7445  if( one_in( explosion_chance ) ) {
7447  const int pow = 120 * ( 1 - std::exp( data.explosion_factor / -5000 *
7448  ( vp.ammo_remaining() * data.fuel_size_factor ) ) );
7449  explosion_handler::explosion( nullptr, global_part_pos3( vp ), pow, 0.7, data.fiery_explosion );
7450  mod_hp( vp, -vp.hp() );
7451  vp.ammo_unset();
7452  }
7453 
7454  return true;
7455 }
void send(const cata::event &) const
Definition: event_bus.cpp:72
bool has_explosion_data() const
Definition: item.cpp:9844
fuel_explosion_data get_explosion_data() const
Definition: item.cpp:9849
@ fuel_tank_explodes
event_bus & get_event_bus()
Definition: game.cpp:13832
void explosion(const Creature *source, const tripoint &p, float power, float factor, bool fire, int casing_mass, float frag_mass)
Queue an explosion at p of intensity (power) with (shrapnel) chunks of shrapnel.
Definition: explosion.cpp:489
float explosion_factor
Definition: material.h:46
int explosion_chance_cold
Definition: material.h:45
int explosion_chance_hot
Definition: material.h:44
float fuel_size_factor
Definition: material.h:48
void ammo_unset()
Remove all fuel, charges or ammunition (if any) from this part.

References vehicle_part::ammo_remaining(), vehicle_part::ammo_unset(), damage_heat, explosion_handler::explosion(), fuel_explosion_data::explosion_chance_cold, fuel_explosion_data::explosion_chance_hot, fuel_explosion_data::explosion_factor, fuel_explosion_data::fiery_explosion, fuel_explosion_data::fuel_size_factor, fuel_tank_explodes, vpart_info::fuel_type, get_event_bus(), item::get_explosion_data(), global_part_pos3(), item::has_explosion_data(), vehicle_part::hp(), vehicle_part::info(), vehicle_part::is_broken(), item, leak_fuel(), mod_hp(), name, one_in(), event_bus::send(), and type.

Referenced by damage_direct().

◆ face_vec()

rl_vec2d vehicle::face_vec ( ) const

◆ find_all_ready_turrets()

std::vector< vehicle_part * > vehicle::find_all_ready_turrets ( bool  manual,
bool  automatic 
)
private

Definition at line 440 of file turret.cpp.

441 {
442  std::vector<vehicle_part *> res;
443  for( vehicle_part *t : turrets() ) {
444  if( ( t->enabled && automatic ) || ( !t->enabled && manual ) ) {
446  res.push_back( t );
447  }
448  }
449  }
450  return res;
451 }
status query() const
Definition: turret.cpp:236
std::vector< vehicle_part * > turrets()
Get all vehicle turrets (excluding any that are destroyed)
Definition: turret.cpp:36
@ manual

References automatic, manual, turret_data::query(), turret_data::ready, turret_query(), and turrets().

Referenced by turrets_aim_and_fire_all_manual(), and turrets_override_automatic_aim().

◆ find_and_split_vehicles()

bool vehicle::find_and_split_vehicles ( map here,
std::set< int >  exclude 
)

Definition at line 2275 of file vehicle.cpp.

2276 {
2277  std::vector<int> valid_parts = all_parts_at_location( part_location_structure );
2278  std::set<int> checked_parts = std::move( exclude );
2279 
2280  std::vector<std::vector <int>> all_vehicles;
2281 
2282  for( size_t cnt = 0; cnt < 4; cnt++ ) {
2283  int test_part = -1;
2284  for( const int &p : valid_parts ) {
2285  if( parts[p].removed ) {
2286  continue;
2287  }
2288  if( checked_parts.find( p ) == checked_parts.end() ) {
2289  test_part = p;
2290  break;
2291  }
2292  }
2293  if( test_part == -1 || static_cast<size_t>( test_part ) > parts.size() ) {
2294  break;
2295  }
2296 
2297  std::queue<std::pair<int, std::vector<int>>> search_queue;
2298 
2299  const auto push_neighbor = [&]( int p, const std::vector<int> &with_p ) {
2300  std::pair<int, std::vector<int>> data( p, with_p );
2301  search_queue.push( data );
2302  };
2303  auto pop_neighbor = [&]() {
2304  std::pair<int, std::vector<int>> result = search_queue.front();
2305  search_queue.pop();
2306  return result;
2307  };
2308 
2309  std::vector<int> veh_parts;
2310  push_neighbor( test_part, parts_at_relative( parts[test_part].mount, true ) );
2311  while( !search_queue.empty() ) {
2312  std::pair<int, std::vector<int>> test_set = pop_neighbor();
2313  test_part = test_set.first;
2314  if( checked_parts.find( test_part ) != checked_parts.end() ) {
2315  continue;
2316  }
2317  for( const int &p : test_set.second ) {
2318  veh_parts.push_back( p );
2319  }
2320  checked_parts.insert( test_part );
2321  for( const point &offset : four_adjacent_offsets ) {
2322  const point dp = parts[test_part].mount + offset;
2323  std::vector<int> all_neighbor_parts = parts_at_relative( dp, true );
2324  int neighbor_struct_part = -1;
2325  for( const int p : all_neighbor_parts ) {
2326  const vehicle_part &vp_neighbor = parts[p];
2327  if( vp_neighbor.removed ) {
2328  continue;
2329  }
2330  if( vp_neighbor.info().location == part_location_structure ) {
2331  neighbor_struct_part = p;
2332  break;
2333  }
2334  }
2335  if( neighbor_struct_part != -1 ) {
2336  push_neighbor( neighbor_struct_part, all_neighbor_parts );
2337  }
2338  }
2339  }
2340  // don't include the first vehicle's worth of parts
2341  if( cnt > 0 ) {
2342  all_vehicles.push_back( veh_parts );
2343  }
2344  }
2345 
2346  if( !all_vehicles.empty() ) {
2347  const std::vector<vehicle *> null_vehicles( all_vehicles.size(), nullptr );
2348  const std::vector<std::vector<point>> null_mounts( all_vehicles.size(), std::vector<point>() );
2349  std::vector<vehicle *> mark_wreckage { this };
2350  if( split_vehicles( here, all_vehicles, null_vehicles, null_mounts, &mark_wreckage ) ) {
2351  for( vehicle *veh : mark_wreckage ) {
2352  if( !veh->has_tag( flag_APPLIANCE ) ) { // Appliances don't turn into wrecks when split
2353  veh->add_tag( "wreckage" ); // wreckages don't get fake parts added
2354  }
2355  }
2356  shift_parts( here, point_zero ); // update the active cache
2357  return true;
2358  }
2359  }
2360  return false;
2361 }
void shift_parts(map &here, const point &delta)
Shifts all parts of the vehicle by the given amounts, and then shifts the vehicle itself in the oppos...
Definition: vehicle.cpp:7252
bool split_vehicles(map &here, const std::vector< std::vector< int >> &new_vehs, const std::vector< vehicle * > &new_vehicles, const std::vector< std::vector< point >> &new_mounts, std::vector< vehicle * > *added_vehicles=nullptr)
Definition: vehicle.cpp:2375
constexpr point point_zero
Definition: point.h:251
static const std::string flag_APPLIANCE("APPLIANCE")

References all_parts_at_location(), flag_APPLIANCE(), four_adjacent_offsets, vehicle_part::info(), vpart_info::location, part_location_structure(), parts, parts_at_relative(), point_zero, vehicle_part::removed, shift_parts(), and split_vehicles().

Referenced by break_off(), veh_interact::complete_vehicle(), and separate_from_grid().

◆ find_lines_of_parts()

std::vector< std::vector< int > > vehicle::find_lines_of_parts ( int  part,
const std::string &  flag 
) const

Returns all parts in the vehicle that have the specified flag in their vpinfo and are on the same X-axis or Y-axis as the input part and are contiguous with each other.

Parameters
partThe part to find adjacent parts to
flagThe flag to match
Returns
A list of lists of indices of all parts sharing the flag and contiguous with the part on the X or Y axis. Returns 0, 1, or 2 lists of indices.

Definition at line 3120 of file vehicle.cpp.

3122 {
3123  const auto possible_parts = get_avail_parts( flag );
3124  std::vector<std::vector<int>> ret_parts;
3125  if( empty( possible_parts ) ) {
3126  return ret_parts;
3127  }
3128 
3129  std::vector<int> x_parts;
3130  std::vector<int> y_parts;
3131 
3132  // start from the real part, otherwise it fails in certain orientations
3134 
3135  const vehicle_part &vp = parts[part];
3136  const vpart_id &part_id = vp.info().id;
3137  const point target = vp.mount;
3138  // create vectors of parts on the same X or Y axis
3139  for( const vpart_reference &vpr : possible_parts ) {
3140  const vehicle_part &vp_other = vpr.part();
3141  const vpart_info &vpi_other = vp_other.info();
3142  if( vp_other.is_unavailable() ||
3143  !vpi_other.has_flag( "MULTISQUARE" ) ||
3144  vpi_other.id != part_id ) {
3145  continue;
3146  }
3147  if( vp_other.mount.x == target.x ) {
3148  x_parts.push_back( vpr.part_index() );
3149  }
3150  if( vp_other.mount.y == target.y ) {
3151  y_parts.push_back( vpr.part_index() );
3152  }
3153  }
3154 
3155  if( x_parts.size() > 1 ) {
3156  std::vector<int> x_ret;
3157  // sort by Y-axis, since they're all on the same X-axis
3158  const auto x_sorter = [&]( const int lhs, const int rhs ) {
3159  return parts[lhs].mount.y > parts[rhs].mount.y;
3160  };
3161  std::sort( x_parts.begin(), x_parts.end(), x_sorter );
3162  int first_part = 0;
3163  int prev_y = parts[ x_parts[ 0 ] ].mount.y;
3164  int i;
3165  bool found_part = x_parts[ 0 ] == part;
3166  for( i = 1; static_cast<size_t>( i ) < x_parts.size(); i++ ) {
3167  // if the Y difference is > 1, there's a break in the run
3168  if( std::abs( parts[ x_parts[ i ] ].mount.y - prev_y ) > 1 ) {
3169  // if we found the part, this is the run we wanted
3170  if( found_part ) {
3171  break;
3172  }
3173  first_part = i;
3174  }
3175  found_part |= x_parts[ i ] == part;
3176  prev_y = parts[ x_parts[ i ] ].mount.y;
3177  }
3178  for( size_t j = first_part; j < static_cast<size_t>( i ); j++ ) {
3179  x_ret.push_back( x_parts[ j ] );
3180  }
3181  ret_parts.push_back( x_ret );
3182  }
3183  if( y_parts.size() > 1 ) {
3184  std::vector<int> y_ret;
3185  const auto y_sorter = [&]( const int lhs, const int rhs ) {
3186  return parts[lhs].mount.x > parts[rhs].mount.x;
3187  };
3188  std::sort( y_parts.begin(), y_parts.end(), y_sorter );
3189  int first_part = 0;
3190  int prev_x = parts[ y_parts[ 0 ] ].mount.x;
3191  int i;
3192  bool found_part = y_parts[ 0 ] == part;
3193  for( i = 1; static_cast<size_t>( i ) < y_parts.size(); i++ ) {
3194  if( std::abs( parts[ y_parts[ i ] ].mount.x - prev_x ) > 1 ) {
3195  if( found_part ) {
3196  break;
3197  }
3198  first_part = i;
3199  }
3200  found_part |= y_parts[ i ] == part;
3201  prev_x = parts[ y_parts[ i ] ].mount.x;
3202  }
3203  for( size_t j = first_part; j < static_cast<size_t>( i ); j++ ) {
3204  y_ret.push_back( y_parts[ j ] );
3205  }
3206  ret_parts.push_back( y_ret );
3207  }
3208  if( y_parts.size() == 1 && x_parts.size() == 1 ) {
3209  ret_parts.push_back( x_parts );
3210  }
3211  return ret_parts;
3212 }
bool is_unavailable(bool carried=true) const
parts are unavailable if broken or if carried is true, if they have the CARRIED flag

References abs(), get_avail_parts(), get_non_fake_part(), vpart_info::has_flag(), vpart_info::id, vehicle_part::info(), vehicle_part::is_unavailable(), vehicle_part::mount, part(), parts, point::x, and point::y.

Referenced by can_close(), find_vehicles_to_rack(), find_vehicles_to_unrack(), lock_or_unlock(), and open_or_close().

◆ find_vehicle()

vehicle * vehicle::find_vehicle ( const tripoint_abs_ms where)
static

Find a possibly off-map vehicle.

If necessary, loads up its submap through the global MAPBUFFER and pulls it from there. For this reason, you should only give it the coordinates of the origin tile of a target vehicle.

Parameters
whereLocation of the other vehicle's origin tile.

Definition at line 5344 of file vehicle.cpp.

5345 {
5346  map &here = get_map();
5347  // Is it in the reality bubble?
5348  if( const optional_vpart_position vp = here.veh_at( where ) ) {
5349  return &vp->vehicle();
5350  }
5351  // Nope. Load up its submap...
5352  point_sm_ms_ib veh_in_sm;
5353  tripoint_abs_sm veh_sm;
5354  std::tie( veh_sm, veh_in_sm ) = project_remain<coords::sm>( where );
5355  const submap *sm = MAPBUFFER.lookup_submap( veh_sm );
5356  if( sm == nullptr ) {
5357  return nullptr;
5358  }
5359 
5360  for( const auto &elem : sm->vehicles ) {
5361  vehicle *found_veh = elem.get();
5362  // TODO: fix point types
5363  if( veh_in_sm.raw() == found_veh->pos ) {
5364  return found_veh;
5365  }
5366  }
5367 
5368  return nullptr;
5369 }
submap * lookup_submap(const tripoint_abs_sm &p)
Get a submap stored in this buffer.
Definition: mapbuffer.cpp:104
Definition: submap.h:70
mapbuffer MAPBUFFER
Definition: mapbuffer.cpp:48
constexpr scale sm
Definition: coordinates.h:39

References get_map(), mapbuffer::lookup_submap(), MAPBUFFER, pos, coords::coord_point_mut< Point, Subpoint, InBounds >::raw(), coords::sm, and map::veh_at().

Referenced by get_connected_vehicles(), get_remote_part(), item::link_to(), item::process_link(), and search_connected_vehicles().

◆ find_vehicles_to_rack()

std::vector< vehicle::rackable_vehicle > vehicle::find_vehicles_to_rack ( int  rack) const

Definition at line 1528 of file vehicle.cpp.

1529 {
1530  std::vector<rackable_vehicle> rackables;
1531  for( const std::vector<int> &maybe_rack : find_lines_of_parts( rack, "BIKE_RACK_VEH" ) ) {
1532  std::vector<int> filtered_rack; // only empty racks
1533  std::copy_if( maybe_rack.begin(), maybe_rack.end(), std::back_inserter( filtered_rack ),
1534  [&]( const int &p ) {
1535  return !parts[p].has_flag( vp_flag::carrying_flag );
1536  } );
1537 
1538  for( const point &offset : four_cardinal_directions ) {
1539  vehicle *veh_matched = nullptr;
1540  std::set<tripoint> parts_matched;
1541  for( const int &rack_part : filtered_rack ) {
1542  const tripoint search_pos = global_part_pos3( rack_part ) + offset;
1543  const optional_vpart_position ovp = get_map().veh_at( search_pos );
1544  if( !ovp || &ovp->vehicle() == this || ovp->vehicle().is_appliance() ) {
1545  continue;
1546  }
1547  vehicle *const test_veh = &ovp->vehicle();
1548  if( test_veh != veh_matched ) { // previous vehicle ended, start gathering parts of new one
1549  veh_matched = test_veh;
1550  parts_matched.clear();
1551  }
1552  parts_matched.insert( search_pos );
1553 
1554  std::set<tripoint> test_veh_points;
1555  for( const vpart_reference &vpr : test_veh->get_all_parts() ) {
1556  if( !vpr.part().removed && !vpr.part().is_fake ) {
1557  test_veh_points.insert( vpr.pos() );
1558  }
1559  }
1560 
1561  // racking is valid when all vehicle parts are exactly 1 tile offset from each free rack part
1562  // not handled: could be multiple racks that can accept same vehicle,
1563  // ( for example U shaped where the prongs each have rack )
1564  if( parts_matched == test_veh_points ) {
1565  const bool already_inserted = std::any_of( rackables.begin(), rackables.end(),
1566  [test_veh]( const rackable_vehicle & r ) {
1567  return r.veh == test_veh;
1568  } );
1569  if( !already_inserted ) {
1570  rackables.push_back( { test_veh->name, test_veh, filtered_rack } );
1571  }
1572  }
1573  }
1574  }
1575  }
1576  return rackables;
1577 }
constexpr std::array< point, 4 > four_cardinal_directions
Definition: point.h:346

References find_lines_of_parts(), four_cardinal_directions, get_all_parts(), get_map(), global_part_pos3(), name, and map::veh_at().

Referenced by build_bike_rack_menu().

◆ find_vehicles_to_unrack()

std::vector< vehicle::unrackable_vehicle > vehicle::find_vehicles_to_unrack ( int  rack) const

Definition at line 1579 of file vehicle.cpp.

1580 {
1581  std::vector<unrackable_vehicle> unrackables;
1582  for( const std::vector<int> &rack_parts : find_lines_of_parts( rack, "BIKE_RACK_VEH" ) ) {
1583  unrackable_vehicle unrackable;
1584 
1585  // a racked vehicle is "finished" by collecting all of its carried parts and carrying racks
1586  // involved, if any parts have been collected add them to the lists and clear the temporary
1587  // variables for the next carried vehicle
1588  const auto commit_vehicle = [&]() {
1589  if( unrackable.racks.empty() ) {
1590  return; // not valid unrackable
1591  }
1592 
1593  // 2 results with the same name either indicate a bug or this rack is a "corner" that scanned
1594  // the vehicle twice: once on the correct axis and once on the wrong axis resulting in a 1 tile
1595  // slice see #47374 for more details. Keep the longest of the two "slices".
1596  const auto same_name = std::find_if( unrackables.begin(), unrackables.end(),
1597  [name = unrackable.name]( const unrackable_vehicle & v ) {
1598  return v.name == name;
1599  } );
1600  if( same_name != unrackables.end() ) {
1601  if( same_name->racks.size() < unrackable.racks.size() ) {
1602  *same_name = unrackable;
1603  }
1604  } else {
1605  unrackables.push_back( unrackable );
1606  }
1607 
1608  unrackable.racks.clear();
1609  unrackable.parts.clear();
1610  unrackable.name.clear();
1611  };
1612 
1613  for( const int &rack_part : rack_parts ) {
1614  const vehicle_part &vp_rack = this->part( rack_part );
1615  if( !vp_rack.has_flag( vp_flag::carrying_flag ) ) {
1616  commit_vehicle();
1617  continue;
1618  }
1619  for( const point &offset : four_cardinal_directions ) {
1620  const std::vector<int> near_parts = parts_at_relative( vp_rack.mount + offset, false );
1621  if( near_parts.empty() ) {
1622  continue;
1623  }
1624  const vehicle_part &vp_near = parts[ near_parts[ 0 ] ];
1625  if( !vp_near.has_flag( vp_flag::carried_flag ) ) {
1626  continue;
1627  }
1628  // if carried_name is different we have 2 separate vehicles racked on same
1629  // rack, commit what we have and reset variables to start collecting parts
1630  // and racks for next carried vehicle.
1631  if( vp_near.carried_name() != unrackable.name ) {
1632  commit_vehicle();
1633  unrackable.name = vp_near.carried_name();
1634  }
1635  for( const int &carried_part : near_parts ) {
1636  unrackable.parts.push_back( carried_part );
1637  }
1638  unrackable.racks.push_back( rack_part );
1639  break; // found parts carried by this rack, bail out from search early
1640  }
1641  }
1642 
1643  commit_vehicle();
1644  }
1645 
1646  // collect total number of parts for each racked vehicle
1647  std::map<std::string, size_t> racked_parts_per_veh;
1648  for( const vehicle_part &vp : real_parts() ) {
1649  racked_parts_per_veh[vp.carried_name()]++;
1650  }
1651  // filter out not vehicles not fully "located" on the given rack (corner-scanned)
1652  unrackables.erase( std::remove_if( unrackables.begin(), unrackables.end(),
1653  [&racked_parts_per_veh]( const unrackable_vehicle & unrackable ) {
1654  return unrackable.parts.size() != racked_parts_per_veh[unrackable.name];
1655  } ), unrackables.end() );
1656 
1657  return unrackables;
1658 }
std::vector< std::reference_wrapper< const vehicle_part > > real_parts() const
Definition: vehicle.cpp:8142
std::string carried_name() const

References carried_flag, vehicle_part::carried_name(), carrying_flag, find_lines_of_parts(), four_cardinal_directions, vehicle_part::has_flag(), vehicle_part::mount, vehicle::unrackable_vehicle::name, name, part(), vehicle::unrackable_vehicle::parts, parts, parts_at_relative(), vehicle::unrackable_vehicle::racks, and real_parts().

Referenced by build_bike_rack_menu(), and merge_rackable_vehicle().

◆ folding_time()

time_duration vehicle::folding_time ( ) const

Definition at line 7607 of file vehicle.cpp.

7608 {
7609  const vehicle_part_range vpr = get_all_parts();
7610  return std::accumulate( vpr.begin(), vpr.end(), time_duration(),
7611  []( time_duration & acc, const vpart_reference & part ) {
7612  return acc + ( part.part().removed ? time_duration() : part.info().get_folding_time() );
7613  } );
7614 }
iterator begin() const
Definition: vpart_range.h:123
iterator end() const
Definition: vpart_range.h:126
time_duration get_folding_time() const
Definition: veh_type.cpp:1146

References generic_vehicle_part_range< range_type >::begin(), generic_vehicle_part_range< range_type >::end(), get_all_parts(), vpart_info::get_folding_time(), vehicle_part::info(), and part().

Referenced by vehicle_folding_activity_actor::vehicle_folding_activity_actor().

◆ forward_velocity()

float vehicle::forward_velocity ( ) const

Definition at line 1580 of file vehicle_move.cpp.

1581 {
1582  rl_vec2d mv = move_vec();
1583  rl_vec2d fv = face_vec();
1584  float dot = mv.dot_product( fv );
1585  return velocity * dot;
1586 }
rl_vec2d move_vec() const
rl_vec2d face_vec() const
float dot(const std::array< int, 3 > &g, const float x, const float y)
Definition: line.h:280
float dot_product(const rl_vec2d &v) const
Definition: line.cpp:777

References dot(), rl_vec2d::dot_product(), face_vec(), move_vec(), and velocity.

Referenced by map::draw_maptile(), pldrive(), and selfdrive().

◆ fuel_capacity()

int vehicle::fuel_capacity ( const itype_id ftype) const

Definition at line 3581 of file vehicle.cpp.

3582 {
3583  if( ftype == fuel_type_battery ) { // batteries get special treatment due to power cables
3584  int64_t capacity = 0;
3585  for( const std::pair<const vehicle *const, float> &pair : search_connected_vehicles() ) {
3586  const vehicle &veh = *pair.first;
3587  for( const int part_idx : veh.batteries ) {
3588  const vehicle_part &vp = veh.parts[part_idx];
3589  capacity += vp.ammo_capacity( fuel_type_battery->ammo->type );
3590  }
3591  }
3592  return capacity;
3593  }
3594  const vehicle_part_range vpr = get_all_parts();
3595  return std::accumulate( vpr.begin(), vpr.end(), int64_t { 0 },
3596  [&ftype]( const int64_t &lhs, const vpart_reference & rhs ) {
3597  if( rhs.part().ammo_current() == ftype && ftype->ammo ) {
3598  return lhs + rhs.part().ammo_capacity( ftype->ammo->type );
3599  }
3600  return lhs;
3601  } );
3602 }
cata::value_ptr< islot_ammo > ammo
Definition: itype.h:1212

References itype::ammo, vehicle_part::ammo_capacity(), batteries, generic_vehicle_part_range< range_type >::begin(), generic_vehicle_part_range< range_type >::end(), fuel_type_battery, get_all_parts(), parts, and search_connected_vehicles().

Referenced by print_fuel_indicator(), and display::vehicle_fuel_percent_text_color().

◆ fuel_items_left()

std::list< item * > vehicle::fuel_items_left ( )

All the individual fuel items that are in all the tanks in the vehicle.

Definition at line 7583 of file vehicle.cpp.

7584 {
7585  std::list<item *> result;
7586  for( vehicle_part &p : parts ) {
7587  if( p.is_fuel_store() && !p.ammo_current().is_null() && !p.base.is_container_empty() ) {
7588  result.push_back( &p.base.only_item() );
7589  }
7590  }
7591  return result;
7592 }

References parts.

◆ fuel_left()

int64_t vehicle::fuel_left ( const itype_id ftype,
const std::function< bool(const vehicle_part &)> &  filter = return_true<const vehicle_part &> 
) const

Definition at line 3516 of file vehicle.cpp.

3518 {
3519  int64_t fl = 0;
3520  if( ftype == fuel_type_battery ) {
3521  for( const std::pair<const vehicle *const, float> &pair : search_connected_vehicles() ) {
3522  const vehicle &veh = *pair.first;
3523  const float loss = pair.second;
3524  for( const int part_idx : veh.batteries ) {
3525  const vehicle_part &vp = veh.parts[part_idx];
3526  if( vp.ammo_current() != fuel_type_battery || !filter( vp ) ) {
3527  continue;
3528  }
3529  fl += vp.ammo_remaining() * ( 1.0f - loss );
3530  }
3531  }
3532  return fl;
3533  }
3534 
3535  for( const int i : fuel_containers ) {
3536  const vehicle_part &part = parts[i];
3537  if( part.ammo_current() != ftype ||
3538  // don't count frozen liquid
3539  ( !part.base.empty() && part.is_tank() &&
3541  continue;
3542  }
3543  fl += part.ammo_remaining();
3544  }
3545 
3546  //muscle engines have infinite fuel
3547  if( ftype == fuel_type_muscle ) {
3548  Character &player_character = get_player_character();
3549  // TODO: Allow NPCs to power those
3550  const optional_vpart_position vp = get_map().veh_at( player_character.pos() );
3551  bool player_controlling = player_in_control( player_character );
3552 
3553  //if the engine in the player tile is a muscle engine, and player is controlling vehicle
3554  if( vp && &vp->vehicle() == this && player_controlling ) {
3555  const int p = avail_part_with_feature( vp->part_index(), VPFLAG_ENGINE );
3556  if( p >= 0 ) {
3557  const vehicle_part &vp = parts[p];
3558  const vpart_info &vpi = vp.info();
3559  if( vp.enabled && vpi.fuel_type == fuel_type_muscle ) {
3560  // intact limbs allow using muscle engines from working
3561  if( ( vpi.has_flag( "MUSCLE_LEGS" ) && player_character.get_working_leg_count() >= 2 ) ||
3562  ( vpi.has_flag( "MUSCLE_ARMS" ) && player_character.has_two_arms_lifting() ) ) {
3563  fl += 10;
3564  }
3565  }
3566  }
3567  }
3568  // As do any other engine flagged as perpetual
3569  } else if( item( ftype ).has_flag( flag_PERPETUAL ) ) {
3570  fl += 10;
3571  }
3572 
3573  return fl;
3574 }
int get_working_leg_count() const
Returns the number of functioning legs.
Definition: character.cpp:2133
bool has_two_arms_lifting() const
Returns true if the character has two functioning arms.
Definition: character.cpp:2083
item & legacy_front()
This function is to aid migration to using nested containers.
Definition: item.cpp:15170
bool empty() const
Definition: item.cpp:15135
int avail_part_with_feature(const point &pt, const std::string &f) const
Returns index of part at mount point pt which has given f flag and is_available(),...
Definition: vehicle.cpp:2805
@ VPFLAG_ENGINE
Definition: veh_type.h:88

References vehicle_part::ammo_current(), vehicle_part::ammo_remaining(), avail_part_with_feature(), vehicle_part::base, batteries, item::empty(), vehicle_part::enabled, filter, flag_PERPETUAL, fuel_containers, vpart_info::fuel_type, fuel_type_battery, fuel_type_muscle, get_map(), get_player_character(), Character::get_working_leg_count(), vpart_info::has_flag(), Character::has_two_arms_lifting(), vehicle_part::info(), vehicle_part::is_tank(), item, item::legacy_front(), item::made_of(), part(), parts, player_in_control(), Creature::pos(), search_connected_vehicles(), SOLID, map::veh_at(), and VPFLAG_ENGINE.

Referenced by act_vehicle_unload_fuel(), turret_data::ammo_remaining(), auto_select_fuel(), beeper_sound(), build_electronics_menu(), can_enable(), consume_fuel(), control_engines(), engine_fuel_left(), activity_handlers::fill_liquid_do_turn(), has_security_working(), honk_horn(), is_alternator_on(), pickveh(), turret_data::prepare_fire(), print_fuel_indicator(), turret_data::query(), game::remoteveh(), iuse::remoteveh_tick(), tool_ammo_available(), update_time(), use_autoclave(), use_dishwasher(), use_washing_machine(), and display::vehicle_fuel_percent_text_color().

◆ fuel_usage()

std::map< itype_id, units::power > vehicle::fuel_usage ( ) const

Maps used fuel to its basic (unscaled by load/strain) consumption.

Definition at line 4834 of file vehicle.cpp.

4835 {
4836  std::map<itype_id, units::power> ret;
4837  for( const int p : engines ) {
4838  const vehicle_part &vp = parts[p];
4839  if( is_perpetual_type( vp ) ) {
4840  continue;
4841  }
4842  ret[vp.fuel_current()] += engine_fuel_usage( vp );
4843  }
4844  return ret;
4845 }
units::power engine_fuel_usage(const vehicle_part &vp) const
Fuel usage for specific engine.
Definition: vehicle.cpp:4822

References engine_fuel_usage(), engines, vehicle_part::fuel_current(), is_perpetual_type(), parts, and cata::hash64_detail::ret.

Referenced by consume_fuel(), and smart_controller_handle_turn().

◆ fuels_left()

std::map< itype_id, int > vehicle::fuels_left ( ) const

All the fuels that are in all the tanks in the vehicle, nicely summed up.

Note that empty tanks don't count at all. The value is the amount as it would be reported by fuel_left, it is always greater than 0. The key is the fuel item type.

Definition at line 7572 of file vehicle.cpp.

7573 {
7574  std::map<itype_id, int> result;
7575  for( const vehicle_part &p : parts ) {
7576  if( p.is_fuel_store() && !p.ammo_current().is_null() ) {
7577  result[ p.ammo_current() ] += p.ammo_remaining();
7578  }
7579  }
7580  return result;
7581 }

References parts.

Referenced by act_vehicle_unload_fuel(), turret_data::ammo_options(), and veh_interact::cant_do().

◆ gain_moves()

void vehicle::gain_moves ( )

Definition at line 6051 of file vehicle.cpp.

6052 {
6053  fuel_used_last_turn.clear();
6055  const bool pl_control = player_in_control( get_player_character() );
6056  if( is_moving() || is_falling ) {
6057  if( !loose_parts.empty() ) {
6058  shed_loose_parts();
6059  }
6060  of_turn = 1 + of_turn_carry;
6061  const int vslowdown = slowdown( velocity );
6062  if( vslowdown > std::abs( velocity ) ) {
6063  if( cruise_velocity && pl_control ) {
6064  velocity = velocity > 0 ? 1 : -1;
6065  } else {
6066  stop();
6067  }
6068  } else if( velocity < 0 ) {
6069  velocity += vslowdown;
6070  } else {
6071  velocity -= vslowdown;
6072  }
6073  is_on_ramp = false;
6074  } else {
6075  of_turn = .001;
6076  }
6077  of_turn_carry = 0;
6078  // cruise control TODO: enable for NPC?
6079  if( ( pl_control || is_following || is_patrolling ) && cruise_velocity != velocity ) {
6080  thrust( cruise_velocity > velocity ? 1 : -1 );
6081  } else if( is_rotorcraft() && velocity == 0 ) {
6082  // rotorcraft uses fuel for hover
6083  // whether it's flying or not is checked inside thrust function
6084  thrust( 0 );
6085  }
6086 
6087  // Force off-map connected vehicles to load by visiting them every time we gain moves.
6088  // This is expensive so we allow a slightly stale result
6089  if( calendar::once_every( 5_turns ) ) {
6090  std::unordered_set<vehicle *> vehs;
6091  get_connected_vehicles( vehs );
6092  }
6093 
6096  }
6097 
6098  // turrets which are enabled will try to reload and then automatically fire
6099  // Turrets which are disabled but have targets set are a special case
6100  for( vehicle_part *e : turrets() ) {
6101  if( e->enabled || e->target.second != e->target.first ) {
6102  automatic_fire_turret( *e );
6103  }
6104  }
6105 
6106  if( velocity < 0 ) {
6107  beeper_sound();
6108  }
6109 }
int slowdown(int velocity) const
void thrust(int thd, int z=0)
void beeper_sound() const
int automatic_fire_turret(vehicle_part &pt)
Definition: turret.cpp:573
void check_falling_or_floating()
void get_connected_vehicles(std::unordered_set< vehicle * > &dest)
Returns a map of connected vehicle pointers to power loss factor: Keys are vehicles connected by POWE...
Definition: vehicle.cpp:5423
void shed_loose_parts(trinary shed_cables=trinary::NONE, const tripoint_bub_ms *dst=nullptr)
Drop parts with UNMOUNT_ON_MOVE onto the ground.
Definition: vehicle.cpp:6976
bool do_environmental_effects() const
Definition: vehicle.cpp:3983
bool check_environmental_effects
Definition: vehicle.h:2365
std::vector< int > loose_parts
Definition: vehicle.h:2182

References abs(), automatic_fire_turret(), beeper_sound(), check_environmental_effects, check_falling_or_floating(), cruise_velocity, do_environmental_effects(), fuel_used_last_turn, get_connected_vehicles(), get_player_character(), is_falling, is_following, is_moving(), is_on_ramp, is_patrolling, is_rotorcraft(), loose_parts, of_turn, of_turn_carry, calendar::once_every(), player_in_control(), shed_loose_parts(), slowdown(), stop(), thrust(), turrets(), and velocity.

Referenced by map::vehmove().

◆ get_all_parts()

vehicle_part_range vehicle::get_all_parts ( ) const

◆ get_all_parts_with_fakes()

vehicle_part_with_fakes_range vehicle::get_all_parts_with_fakes ( bool  with_inactive = false) const

Definition at line 8218 of file vehicle.cpp.

8219 {
8220  return vehicle_part_with_fakes_range( const_cast<vehicle &>( *this ), with_inactive );
8221 }

Referenced by map::add_vehicle_to_cache(), map::build_seen_cache(), map::do_vehicle_caching(), parts_at_relative(), and map::scent_blockers().

◆ get_angle_from_targ()

units::angle vehicle::get_angle_from_targ ( const tripoint targ) const

Definition at line 843 of file vehicle.cpp.

844 {
845  tripoint vehpos = global_square_location().raw();
846  rl_vec2d facevec = face_vec();
847  point rel_pos_target = targ.xy() - vehpos.xy();
848  rl_vec2d targetvec = rl_vec2d( rel_pos_target.x, rel_pos_target.y );
849  // cross product
850  double crossy = ( facevec.x * targetvec.y ) - ( targetvec.x * facevec.y );
851  // dot product.
852  double dotx = ( facevec.x * targetvec.x ) + ( facevec.y * targetvec.y );
853 
854  return units::atan2( crossy, dotx );
855 }
units::angle atan2(double y, double x)
Definition: units.h:1122
float y
Definition: line.h:282
float x
Definition: line.h:281

References units::atan2(), face_vec(), global_square_location(), coords::coord_point_mut< Point, Subpoint, InBounds >::raw(), rl_vec2d::x, point::x, tripoint::xy(), rl_vec2d::y, and point::y.

Referenced by do_towing_move(), and drive_to_local_target().

◆ get_any_parts() [1/2]

vehicle_part_with_feature_range< std::string > vehicle::get_any_parts ( std::string  feature) const

Yields a range of parts of this vehicle that each have the given feature and not removed.

The enabled status of the part is ignored.

Definition at line 3037 of file vehicle.cpp.

3038 {
3039  return vehicle_part_with_feature_range<std::string>( const_cast<vehicle &>( *this ),
3040  std::move( feature ), part_status_flag::any );
3041 }
A range that contains parts that have a given feature and (optionally) are not broken.
Definition: vpart_range.h:175
static T_id feature(const tripoint &p)

References any, and feature().

Referenced by act_vehicle_siphon(), build_bike_rack_menu(), build_electronics_menu(), veh_app_interact::can_siphon(), veh_interact::cant_do(), veh_interact::display_stats(), vehicle_folding_activity_actor::fold_vehicle(), map::generate_lightmap(), get_tow_part(), item::link_to(), merge_rackable_vehicle(), MapExtras::mx_helicopter(), map::process_items_in_vehicle(), refresh_active_item_cache(), vehicle_prototype::save_vehicle_as_prototype(), and veh_app_interact::siphon().

◆ get_any_parts() [2/2]

vehicle_part_with_feature_range< vpart_bitflags > vehicle::get_any_parts ( vpart_bitflags  f) const

Definition at line 3043 of file vehicle.cpp.

3045 {
3046  return vehicle_part_with_feature_range<vpart_bitflags>( const_cast<vehicle &>( *this ), feature,
3048 }

References any, and feature().

◆ get_avail_parts() [1/2]

vehicle_part_with_feature_range< std::string > vehicle::get_avail_parts ( std::string  feature) const

Yields a range of parts of this vehicle that each have the given feature and are available: not broken, removed, or part of a carried vehicle.

The enabled status of the part is ignored.

Definition at line 3007 of file vehicle.cpp.

3008 {
3009  return vehicle_part_with_feature_range<std::string>( const_cast<vehicle &>( *this ),
3010  std::move( feature ),
3013 }
part_status_flag
Definition: vehicle.h:99

References available, feature(), and working.

Referenced by add_electronic_toggle(), beeper_sound(), boarded_parts(), build_interact_menu(), veh_interact::can_potentially_install(), veh_interact::can_self_jack(), control_doors(), map::detach_vehicle(), disable_smart_controller_if_needed(), npc::execute_action(), find_lines_of_parts(), get_riders(), hackveh(), honk_horn(), pickveh(), pldrive(), relocate_passengers(), remote_controlled(), iuse::remoteveh(), smart_controller_handle_turn(), turrets_set_targeting(), and veh_interact::update_part_requirements().

◆ get_avail_parts() [2/2]

vehicle_part_with_feature_range< vpart_bitflags > vehicle::get_avail_parts ( vpart_bitflags  f) const

Definition at line 3015 of file vehicle.cpp.

3017 {
3018  return vehicle_part_with_feature_range<vpart_bitflags>( const_cast<vehicle &>( *this ), feature,
3021 }

References available, feature(), and working.

◆ get_bounding_box()

bounding_box vehicle::get_bounding_box ( bool  use_precalc = true,
bool  no_fake = false 
)

Definition at line 8056 of file vehicle.cpp.

8057 {
8058  int min_x = INT_MAX;
8059  int max_x = INT_MIN;
8060  int min_y = INT_MAX;
8061  int max_y = INT_MIN;
8062 
8063  face.init( turn_dir );
8064 
8065  precalc_mounts( 0, turn_dir, point() );
8066 
8067  for( const tripoint &p : get_points( true, no_fake ) ) {
8068  point pt;
8069  if( use_precalc ) {
8070  const int i_use = 0;
8071  int part_idx = part_at( p.xy() );
8072  if( part_idx < 0 ) {
8073  continue;
8074  }
8075  pt = parts[part_idx].precalc[i_use].xy();
8076  } else {
8077  pt = p.xy();
8078  }
8079  if( pt.x < min_x ) {
8080  min_x = pt.x;
8081  }
8082  if( pt.x > max_x ) {
8083  max_x = pt.x;
8084  }
8085  if( pt.y < min_y ) {
8086  min_y = pt.y;
8087  }
8088  if( pt.y > max_y ) {
8089  max_y = pt.y;
8090  }
8091  }
8092  bounding_box b;
8093  b.p1 = point( min_x, min_y );
8094  b.p2 = point( max_x, max_y );
8095  return b;
8096 }
void precalc_mounts(int idir, const units::angle &dir, const point &pivot)
Definition: vehicle.cpp:3338
int part_at(const point &dp) const
Definition: vehicle.cpp:3214

References b, face, get_points(), tileray::init(), part_at(), parts, point, precalc_mounts(), turn_dir, point::x, and point::y.

Referenced by merge_appliance_into_grid(), and MapExtras::mx_helicopter().

◆ get_connected_vehicles()

void vehicle::get_connected_vehicles ( std::unordered_set< vehicle * > &  dest)

Returns a map of connected vehicle pointers to power loss factor: Keys are vehicles connected by POWER_TRANSFER parts, includes self Values are line loss, 0.01 corresponds to 1% charge loss to wire resistance May load the connected vehicles' submaps Templated to support const and non-const vehicle*.

Definition at line 5423 of file vehicle.cpp.

5424 {
5425  for( const int part_idx : loose_parts ) {
5426  const vehicle_part &vp = part( part_idx );
5427  if( !vp.info().has_flag( VPFLAG_POWER_TRANSFER ) ) {
5428  continue;
5429  }
5430  vehicle *v_next = find_vehicle( tripoint_abs_ms( vp.target.second ) );
5431  if( v_next == nullptr ) {
5432  continue;
5433  }
5434  if( dest.find( v_next ) != dest.end() ) {
5435  continue; // Already found
5436  }
5437  dest.insert( v_next );
5438  v_next->get_connected_vehicles( dest );
5439  }
5440 }
static vehicle * find_vehicle(const tripoint_abs_ms &where)
Find a possibly off-map vehicle.
Definition: vehicle.cpp:5344

References find_vehicle(), get_connected_vehicles(), vpart_info::has_flag(), vehicle_part::info(), loose_parts, part(), vehicle_part::target, and VPFLAG_POWER_TRANSFER.

Referenced by gain_moves(), get_connected_vehicles(), and map::vehmove().

◆ get_debug_overlay_data()

std::vector< std::tuple< point, int, std::string > > vehicle::get_debug_overlay_data ( ) const

Definition at line 1264 of file vehicle_autodrive.cpp.

1265 {
1266  static const std::vector<std::string> debug_what = { "valid_position", "omt" };
1267  std::vector<std::tuple<point, int, std::string>> ret;
1268 
1269  const tripoint_abs_ms veh_pos = global_square_location();
1271  ret.emplace_back( ( autodrive_local_target - veh_pos.raw() ).xy(), catacurses::red, "T" );
1272  }
1273  for( const point &pt_elem : collision_check_points ) {
1274  ret.emplace_back( pt_elem - veh_pos.raw().xy(), catacurses::yellow, "C" );
1275  }
1276 
1278  return ret;
1279  }
1280  const auto_navigation_data &data = active_autodrive_controller->get_data();
1281 
1282  const orientation dir = to_orientation( face.dir() );
1283  for( const std::string &debug_str : debug_what ) {
1284  if( debug_str == "profiles" ) {
1285  const vehicle_profile &profile = data.profile( dir );
1286  for( const point &p : profile.occupied_zone ) {
1287  if( p.x == 0 && p.y == 0 ) {
1288  ret.emplace_back( p, catacurses::cyan, to_string( dir ) );
1289  } else {
1290  ret.emplace_back( p, catacurses::green, "x" );
1291  }
1292  }
1293  for( const point &p : profile.collision_points ) {
1294  ret.emplace_back( p, catacurses::red, "o" );
1295  }
1296  } else if( debug_str == "is_obstacle" ) {
1297  for( int dx = 0; dx < NAV_VIEW_SIZE_X; dx++ ) {
1298  for( int dy = 0; dy < NAV_VIEW_SIZE_Y; dy++ ) {
1299  const bool obstacle = data.is_obstacle[dx][dy];
1300  const int color = obstacle ? catacurses::red : catacurses::green;
1301  const point pt = data.view_to_map.transform( point( dx, dy ) ) - veh_pos.raw().xy();
1302  ret.emplace_back( pt, color, obstacle ? "o" : "x" );
1303  }
1304  }
1305  } else if( debug_str == "valid_position" ) {
1306  const orientation tdir = data.nav_to_map.inverse().transform( dir );
1307  for( int dx = 0; dx < NAV_MAP_SIZE_X; dx++ ) {
1308  for( int dy = 0; dy < NAV_MAP_SIZE_Y; dy++ ) {
1309  const point nav_pt( dx, dy );
1310  const bool valid = data.valid_position( tdir, nav_pt );
1311  const int color = valid ? catacurses::green : catacurses::red;
1312  const point pt = data.nav_to_map.transform( nav_pt ) - veh_pos.raw().xy();
1313  ret.emplace_back( pt, color, to_string( dir ) );
1314  }
1315  }
1316  } else if( debug_str == "goal_zone" ) {
1317  std::unordered_map<point, bool> goal_map;
1318  for( const node_address &addr : data.goal_zone ) {
1319  goal_map[addr.get_point()] |= data.nav_to_map.transform( addr.facing_dir ) == dir;
1320  }
1321  for( const auto &entry : goal_map ) {
1322  const point pt = data.nav_to_map.transform( entry.first ) - veh_pos.raw().xy();
1323  const int color = entry.second ? catacurses::green : catacurses::yellow + 8;
1324  ret.emplace_back( pt, color, "g" );
1325  }
1326  } else if( debug_str == "goal_points" ) {
1327  for( point p : data.goal_points ) {
1328  const point pt = data.nav_to_map.transform( p ) - veh_pos.raw().xy();
1329  ret.emplace_back( pt, catacurses::white, "G" );
1330  }
1331  } else if( debug_str == "path" ) {
1332  for( const navigation_step &step : data.path ) {
1333  ret.emplace_back( ( step.pos - veh_pos ).raw().xy(), 8 + catacurses::yellow,
1334  to_string( step.steering_dir ) );
1335  }
1336  } else if( debug_str == "omt" ) {
1337  const point offset = ( project_to<coords::ms>( data.current_omt ) - veh_pos ).raw().xy();
1338  static const std::vector<point> corners = {point_zero, {0, OMT_SIZE - 1}, {OMT_SIZE - 1, 0}, {OMT_SIZE - 1, OMT_SIZE - 1}};
1339  for( point corner : corners ) {
1340  ret.emplace_back( corner + offset, catacurses::cyan, "+" );
1341  }
1342  }
1343  }
1344  return ret;
1345 }
std::set< point > collision_check_points
Definition: vehicle.h:992
static nc_color color(const T_t &t)
@ corner
Definition: enums.h:411
Data structure that caches all the data needed in order to navigate from one OMT to the next OMT alon...
vehicle_profile & profile(orientation dir)
std::array< point, NAV_MAP_NUM_OMT > goal_points
coord_transformation nav_to_map
std::unordered_set< node_address, node_address_hasher > goal_zone
std::vector< navigation_step > path
cata::mdarray< bool, point, NAV_VIEW_SIZE_X, NAV_VIEW_SIZE_Y > is_obstacle
coord_transformation view_to_map
bool & valid_position(orientation dir, point p)
tripoint_abs_omt current_omt
point transform(const point &p) const
coord_transformation inverse() const
Data type describing how what driving actions to perform at a given location in order to follow the c...
orientation steering_dir
tripoint_abs_ms pos
The address of a navigation node, i.e.
orientation facing_dir
point get_point() const
Data type representing the convex hull of a vehicle under a particular rotation.
std::vector< point > collision_points
std::vector< point > occupied_zone
static std::string to_string(orientation dir)
static constexpr int OMT_SIZE
static constexpr int NAV_MAP_SIZE_X
static constexpr int NAV_MAP_SIZE_Y
orientation
Data type representing a vehicle orientation, which corresponds to an angle that is a multiple of TUR...
static constexpr int NAV_VIEW_SIZE_Y
static constexpr int NAV_VIEW_SIZE_X

References active_autodrive_controller, autodrive_local_target, collision_check_points, vehicle_profile::collision_points, color(), corner, auto_navigation_data::current_omt, catacurses::cyan, tileray::dir(), face, node_address::facing_dir, node_address::get_point(), global_square_location(), auto_navigation_data::goal_points, auto_navigation_data::goal_zone, catacurses::green, coord_transformation::inverse(), auto_navigation_data::is_obstacle, NAV_MAP_SIZE_X, NAV_MAP_SIZE_Y, auto_navigation_data::nav_to_map, NAV_VIEW_SIZE_X, NAV_VIEW_SIZE_Y, vehicle_profile::occupied_zone, OMT_SIZE, auto_navigation_data::path, point, point_zero, navigation_step::pos, auto_navigation_data::profile(), coords::coord_point_mut< Point, Subpoint, InBounds >::raw(), catacurses::red, cata::hash64_detail::ret, navigation_step::steering_dir, to_orientation(), to_string(), coord_transformation::transform(), tripoint_zero, auto_navigation_data::valid_position(), auto_navigation_data::view_to_map, catacurses::white, point::x, point::y, and catacurses::yellow.

◆ get_display_of_tile()

vpart_display vehicle::get_display_of_tile ( const point dp,
bool  rotate = true,
bool  include_fake = true,
bool  below_roof = true,
bool  roof = true 
) const

Definition at line 59 of file vehicle_display.cpp.

61 {
62  const int part_idx = part_displayed_at( dp, include_fake, below_roof, roof );
63  if( part_idx == -1 ) {
64  debugmsg( "no display part at mount (%d, %d)", dp.x, dp.y );
65  return {};
66  }
67 
68  const vehicle_part &vp = part( part_idx );
69  const vpart_info &vpi = vp.info();
70 
71  auto variant_it = vpi.variants.find( vp.variant );
72  if( variant_it == vpi.variants.end() ) {
73  // shouldn't happen but just in case...
74  variant_it = vpi.variants.begin();
75  const std::string fallback_variant = variant_it->first;
76  debugmsg( "part '%s' uses non-existent variant '%s' setting to '%s'",
77  vpi.id.str(), vp.variant, fallback_variant );
78  vehicle_part &vp_cast = const_cast<vehicle_part &>( vp );
79  vp_cast.variant = fallback_variant;
80  }
81  const vpart_variant &vv = variant_it->second;
82 
83  vpart_display ret( vp );
84  ret.is_broken = vp.is_broken();
85  ret.is_open = vp.open && vpi.has_flag( VPFLAG_OPENABLE );
86  ret.color = ret.is_broken ? vpi.color_broken : vpi.color;
87 
88  if( ret.is_open ) { // open door (or similar OPENABLE part)
89  ret.symbol = '\'';
90  ret.symbol_curses = '\'';
91  } else {
92  const units::angle direction = rotate ? 270_degrees - face.dir() : 0_degrees;
93  ret.symbol = vv.get_symbol( direction, ret.is_broken );
94  ret.symbol_curses = vpart_variant::get_symbol_curses( ret.symbol );
95  }
96 
97  // curtain color override
98  const int curtains = part_with_feature( dp, VPFLAG_CURTAIN, true );
99  if( curtains >= 0 ) {
100  const vehicle_part &vp_curtain = parts[curtains];
101  if( !vp_curtain.open && part_with_feature( dp, VPFLAG_WINDOW, true ) >= 0 ) {
102  ret.color = vp_curtain.info().color;
103  }
104  }
105 
106  // armor color override
107  if( get_option<bool>( "VEHICLE_ARMOR_COLOR" ) ) {
108  const int parm = part_with_feature( dp, VPFLAG_ARMOR, true );
109  if( parm != -1 ) {
110  const vehicle_part &vp_armor = parts[parm];
111  ret.color = vp_armor.info().color;
112  }
113  }
114 
115  // blood color override
116  if( vp.blood > 200 ) {
117  ret.color = c_red;
118  } else if( vp.blood > 0 ) {
119  ret.color = c_light_red;
120  }
121 
122  // if cargo has items color is inverted
123  const int cargo_part = part_with_feature( dp, VPFLAG_CARGO, true );
124  if( cargo_part >= 0 && !get_items( part( cargo_part ) ).empty() ) {
125  ret.has_cargo = true;
126  ret.color = invert_color( ret.color );
127  }
128 
129  return ret;
130 }
int part_displayed_at(const point &dp, bool include_fake=false, bool below_roof=true, bool roof=true) const
Returns which part (as an index into the parts list) is the one that will be displayed for the given ...
Definition: vehicle.cpp:3246
std::map< std::string, vpart_variant > variants
Definition: veh_type.h:342
nc_color color
Color of part for different states.
Definition: veh_type.h:378
nc_color color_broken
Definition: veh_type.h:379
int get_symbol_curses(units::angle direction, bool is_broken) const
Definition: veh_type.cpp:1191
char32_t get_symbol(units::angle direction, bool is_broken) const
Definition: veh_type.cpp:1167
nc_color invert_color(const nc_color &c)
Definition: color.cpp:540
#define c_light_red
Definition: color.h:25
#define c_red
Definition: color.h:19
direction
Definition: line.h:42
void curtains(Character &you, const tripoint &examp)
Definition: iexamine.cpp:4868
std::string variant
If it's a part with variants, which variant it is.
Definition: vehicle.h:529
int blood
how much blood covers part (in turns).
Definition: vehicle.h:494
@ VPFLAG_CURTAIN
Definition: veh_type.h:93
@ VPFLAG_ARMOR
Definition: veh_type.h:58
@ VPFLAG_WINDOW
Definition: veh_type.h:92
static point rotate(point p, quad_rotation rotation)

References vehicle_part::blood, c_light_red, c_red, vpart_info::color, vpart_info::color_broken, iexamine::curtains(), debugmsg, tileray::dir(), face, get_items(), vpart_variant::get_symbol(), vpart_variant::get_symbol_curses(), vpart_info::has_flag(), vpart_info::id, vehicle_part::info(), invert_color(), vehicle_part::is_broken(), vehicle_part::open, part(), part_displayed_at(), part_with_feature(), parts, cata::hash64_detail::ret, rotate(), string_id< T >::str(), vehicle_part::variant, vpart_info::variants, VPFLAG_ARMOR, VPFLAG_CARGO, VPFLAG_CURTAIN, VPFLAG_OPENABLE, VPFLAG_WINDOW, point::x, and point::y.

Referenced by veh_interact::display_veh(), map::draw_from_above(), map::draw_maptile(), and vehicle_prototype::save_vehicle_as_prototype().

◆ get_edge_info()

vpart_edge_info vehicle::get_edge_info ( const point mount) const
private

Definition at line 6479 of file vehicle.cpp.

6480 {
6481  point forward = mount + point_east;
6482  point aft = mount + point_west;
6483  point left = mount + point_north;
6484  point right = mount + point_south;
6485  int f_index = -1;
6486  int a_index = -1;
6487  int l_index = -1;
6488  int r_index = -1;
6489  bool left_side = false;
6490  bool right_side = false;
6491  if( relative_parts.find( forward ) != relative_parts.end() &&
6492  !parts.at( relative_parts.at( forward ).front() ).is_fake ) {
6493  f_index = relative_parts.at( forward ).front();
6494  }
6495  if( relative_parts.find( aft ) != relative_parts.end() &&
6496  !parts.at( relative_parts.at( aft ).front() ).is_fake ) {
6497  a_index = relative_parts.at( aft ).front();
6498  }
6499  if( relative_parts.find( left ) != relative_parts.end() &&
6500  !parts.at( relative_parts.at( left ).front() ).is_fake ) {
6501  l_index = relative_parts.at( left ).front();
6502  if( parts.at( relative_parts.at( left ).front() ).info().has_flag( "PROTRUSION" ) ) {
6503  left_side = true;
6504  }
6505  }
6506  if( relative_parts.find( right ) != relative_parts.end() &&
6507  !parts.at( relative_parts.at( right ).front() ).is_fake ) {
6508  r_index = relative_parts.at( right ).front();
6509  if( parts.at( relative_parts.at( right ).front() ).info().has_flag( "PROTRUSION" ) ) {
6510  right_side = true;
6511  }
6512  }
6513  return vpart_edge_info( f_index, a_index, l_index, r_index, left_side, right_side );
6514 }

References left, parts, point_east, point_north, point_south, point_west, relative_parts, and right.

Referenced by refresh().

◆ get_enabled_parts() [1/2]

vehicle_part_with_feature_range< std::string > vehicle::get_enabled_parts ( std::string  feature) const

Yields a range of parts of this vehicle that each have the given feature and are enabled and available: not broken, removed, or part of a carried vehicle.

Definition at line 3050 of file vehicle.cpp.

3052 {
3053  return vehicle_part_with_feature_range<std::string>( const_cast<vehicle &>( *this ),
3054  std::move( feature ),
3058 }

References available, enabled, feature(), and working.

Referenced by crash_terrain_around(), operate_planter(), operate_reaper(), operate_scoop(), play_chimes(), play_music(), power_parts(), and transform_terrain().

◆ get_enabled_parts() [2/2]

vehicle_part_with_feature_range< vpart_bitflags > vehicle::get_enabled_parts ( vpart_bitflags  f) const

Definition at line 3060 of file vehicle.cpp.

3062 {
3063  return vehicle_part_with_feature_range<vpart_bitflags>( const_cast<vehicle &>( *this ), feature,
3067 }

References available, enabled, feature(), and working.

◆ get_exhaust_part()

std::pair< int, double > vehicle::get_exhaust_part ( ) const

Definition at line 8290 of file vehicle.cpp.

8291 {
8292  double muffle = 1.0;
8293  double m = 0.0;
8294  int exhaust_part = -1;
8295  for( int part : mufflers ) {
8296  const vehicle_part &vp = parts[ part ];
8297  m = 1.0 - ( 1.0 - vp.info().bonus / 100.0 ) * vp.health_percent();
8298  if( m < muffle ) {
8299  muffle = m;
8300  exhaust_part = part;
8301  }
8302  }
8303  return std::make_pair( exhaust_part, muffle );
8304 }
std::vector< int > mufflers
Definition: vehicle.h:2193
double health_percent() const
Current part health as a percentage of maximum, with 1.0 being perfect condition.

References vpart_info::bonus, vehicle_part::health_percent(), vehicle_part::info(), mufflers, part(), and parts.

Referenced by idle(), and noise_and_smoke().

◆ get_folded_item()

item vehicle::get_folded_item ( ) const

Definition at line 7625 of file vehicle.cpp.

7626 {
7627  item folded( "generic_folded_vehicle", calendar::turn );
7628  const std::vector<std::reference_wrapper<const vehicle_part>> &parts = real_parts();
7629  try {
7630  std::ostringstream veh_data;
7631  JsonOut json( veh_data );
7632  json.write( parts );
7633  folded.set_var( "folded_parts", veh_data.str() );
7634  } catch( const JsonError &e ) {
7635  debugmsg( "Error storing vehicle: %s", e.c_str() );
7636  return folded;
7637  }
7638 
7639  units::volume folded_volume = 0_ml;
7640  int sum_of_damage = 0;
7641  int num_of_parts = 0;
7642  for( const vehicle_part &vp : real_parts() ) {
7643  folded_volume += vp.info().folded_volume.value_or( 0_ml );
7644  sum_of_damage += vp.damage();
7645  num_of_parts++;
7646  }
7647 
7648  if( num_of_parts == 0 ) {
7649  debugmsg( "Error storing vehicle: 0 real parts" );
7650  return folded;
7651  }
7652 
7653  // snapshot average damage of parts into both item's hp and item variable
7654  const int avg_part_damage = static_cast<int>( sum_of_damage / num_of_parts );
7655 
7656  folded.set_var( "tracking", tracking_on ? 1 : 0 );
7657  folded.set_var( "weight", to_milligram( total_mass() ) );
7658  folded.set_var( "volume", folded_volume / units::legacy_volume_factor );
7659  folded.set_var( "name", string_format( _( "folded %s" ), name ) );
7660  folded.set_var( "vehicle_name", name );
7661  folded.set_var( "unfolding_time", to_moves<int>( unfolding_time() ) );
7662  folded.set_var( "avg_part_damage", avg_part_damage );
7663  folded.set_damage( avg_part_damage );
7664  std::string desc = string_format( _( "A folded %s." ), name )
7665  .append( "\n\n" )
7666  .append( string_format( _( "It will take %s to unfold." ), to_string( unfolding_time() ) ) );
7667  folded.set_var( "description", desc );
7668 
7669  return folded;
7670 }
std::string to_string(const time_duration &d, const bool compact)
Returns a string showing a duration.
Definition: calendar.cpp:546
const char * c_str() const noexcept
Definition: json_error.h:11
Definition: json.h:736
time_duration unfolding_time() const
Definition: vehicle.cpp:7616
time_point turn
Definition: calendar.cpp:38
constexpr value_type to_milligram(const quantity< value_type, mass_in_milligram_tag > &v)
Definition: units.h:358
constexpr volume legacy_volume_factor
Definition: units.h:328

References _, JsonError::c_str(), debugmsg, units::legacy_volume_factor, name, parts, real_parts(), item::set_damage(), item::set_var(), string_format(), units::to_milligram(), to_string(), total_mass(), tracking_on, calendar::turn, unfolding_time(), and JsonOut::write().

Referenced by vehicle_folding_activity_actor::fold_vehicle().

◆ get_harnessed_animal()

monster * vehicle::get_harnessed_animal ( ) const

Definition at line 1293 of file vehicle_move.cpp.

1294 {
1295  for( size_t e = 0; e < parts.size(); e++ ) {
1296  const vehicle_part &vp = parts[ e ];
1297  if( vp.info().fuel_type == fuel_type_animal ) {
1298  monster *mon = get_monster( e );
1299  if( mon && mon->has_effect( effect_harnessed ) && mon->has_effect( effect_pet ) ) {
1300  return mon;
1301  }
1302  }
1303  }
1304  return nullptr;
1305 }
static const efftype_id effect_pet("pet")
static const efftype_id effect_harnessed("harnessed")
static const itype_id fuel_type_animal("animal")

References effect_harnessed, effect_pet, vpart_info::fuel_type, fuel_type_animal, get_monster(), Creature::has_effect(), vehicle_part::info(), and parts.

Referenced by game::control_vehicle(), game::grabbed_veh_move(), player_in_control(), pldrive(), selfdrive(), and steering_effectiveness().

◆ get_items() [1/2]

vehicle_stack vehicle::get_items ( const vehicle_part vp) const

◆ get_items() [2/2]

vehicle_stack vehicle::get_items ( vehicle_part vp)

Definition at line 5917 of file vehicle.cpp.

5918 {
5919  return vehicle_stack( *this, vp );
5920 }

◆ get_monster()

monster * vehicle::get_monster ( int  p) const

◆ get_next_shifted_index()

int vehicle::get_next_shifted_index ( int  original_index,
Character you 
) const

Definition at line 3091 of file vehicle.cpp.

3092 {
3093  int ret_index = original_index;
3094  bool found_shifted_index = false;
3095  for( const vpart_reference &vpr : get_all_parts() ) {
3096  if( you.get_value( "veh_index_type" ) == vpr.info().name() ) {
3097  ret_index = vpr.part_index();
3098  found_shifted_index = true;
3099  break;
3100  }
3101  }
3102  if( !found_shifted_index ) {
3103  // we are probably down to a few parts left, and things get messy here, so an alternative index maybe can't be found
3104  // if loads of npcs are all removing parts at the same time.
3105  // if that's the case, just bail out and give up, somebody else is probably doing the job right now anyway.
3106  return -1;
3107  } else {
3108  return ret_index;
3109  }
3110 }
std::string get_value(const std::string &key) const
Definition: creature.cpp:1959

References get_all_parts(), and Creature::get_value().

Referenced by veh_interact::complete_vehicle(), and vehicle_activity().

◆ get_non_fake_part()

int vehicle::get_non_fake_part ( int  part_num) const

Definition at line 8108 of file vehicle.cpp.

8109 {
8110  if( part_num < 0 || part_num >= part_count() ) {
8111  debugmsg( "get_non_fake_part(%d) returning -1 on '%s', which has %d parts.",
8112  part_num, disp_name(), parts.size() );
8113  return -1;
8114  }
8115  const vehicle_part &vp = parts[part_num];
8116  return vp.is_fake ? vp.fake_part_to : part_num;
8117 }

References debugmsg, disp_name(), vehicle_part::fake_part_to, vehicle_part::is_fake, part_count(), and parts.

Referenced by build_interact_menu(), can_close(), damage(), find_lines_of_parts(), map::move_vehicle(), and map::vehicle_vehicle_collision().

◆ get_old_owner()

faction_id vehicle::get_old_owner ( ) const
inline

Definition at line 980 of file vehicle.h.

980  {
981  return old_owner;
982  }

References old_owner.

Referenced by is_old_owner().

◆ get_owner()

faction_id vehicle::get_owner ( ) const
inline

Definition at line 977 of file vehicle.h.

977  {
978  return owner;
979  }

References owner.

Referenced by veh_interact::do_main_loop(), vehicle_part::get_targeting_npc(), handle_potential_theft(), is_owned_by(), place_spawn_items(), and place_zones().

◆ get_owner_name()

std::string vehicle::get_owner_name ( ) const

Definition at line 4668 of file vehicle.cpp.

4669 {
4670  if( !g->faction_manager_ptr->get( owner ) ) {
4671  debugmsg( "vehicle::get_owner_name() vehicle %s has no valid nor null faction id ", disp_name() );
4672  return _( "no owner" );
4673  }
4674  return _( g->faction_manager_ptr->get( owner )->name );
4675 }

References _, debugmsg, disp_name(), g, and owner.

Referenced by veh_interact::display_name(), and handle_potential_theft().

◆ get_parts_at() [1/3]

std::vector< vehicle_part * > vehicle::get_parts_at ( const tripoint pos,
const std::string &  flag,
part_status_flag  condition 
)

Get all enabled, available, unbroken vehicle parts at specified position.

Parameters
posposition to check
flagif set only flags with this part will be considered
conditionenum to include unabled, unavailable, and broken parts

Definition at line 2855 of file vehicle.cpp.

2857 {
2858  // TODO: provide access to fake parts via argument ?
2859  const tripoint relative_pos = pos - global_pos3();
2860  std::vector<vehicle_part *> res;
2861  for( const vpart_reference &vpr : get_all_parts() ) {
2862  if( vpr.part().precalc[ 0 ] != relative_pos ) {
2863  continue;
2864  }
2865  if( !vpr.part().removed &&
2866  ( flag.empty() || vpr.part().info().has_flag( flag ) ) &&
2867  ( !( condition & part_status_flag::enabled ) || vpr.part().enabled ) &&
2868  ( !( condition & part_status_flag::working ) || !vpr.part().is_broken() ) ) {
2869  res.push_back( &vpr.part() );
2870  }
2871  }
2872  return res;
2873 }

References enabled, get_all_parts(), global_pos3(), pos, and working.

Referenced by map::add_vehicle_to_map(), build_interact_menu(), can_do_activity_there(), enclosed_at(), get_parts_at(), idle(), make_active(), monster::monster_move_in_vehicle(), Character::move_in_vehicle(), MapExtras::mx_helicopter(), Character::process_effects(), monster::process_effects(), and turret_query().

◆ get_parts_at() [2/3]

std::vector< const vehicle_part * > vehicle::get_parts_at ( const tripoint pos,
const std::string &  flag,
part_status_flag  condition 
) const

Definition at line 2882 of file vehicle.cpp.

2885 {
2886  const tripoint relative_pos = pos - global_pos3();
2887  std::vector<const vehicle_part *> res;
2888  for( const vpart_reference &vpr : get_all_parts() ) {
2889  if( vpr.part().precalc[ 0 ] != relative_pos ) {
2890  continue;
2891  }
2892  if( !vpr.part().removed &&
2893  ( flag.empty() || vpr.part().info().has_flag( flag ) ) &&
2894  ( !( condition & part_status_flag::enabled ) || vpr.part().enabled ) &&
2895  ( !( condition & part_status_flag::working ) || !vpr.part().is_broken() ) ) {
2896  res.push_back( &vpr.part() );
2897  }
2898  }
2899  return res;
2900 }

References enabled, get_all_parts(), global_pos3(), pos, and working.

◆ get_parts_at() [3/3]

std::vector< vehicle_part * > vehicle::get_parts_at ( const tripoint_bub_ms pos,
const std::string &  flag,
part_status_flag  condition 
)

Definition at line 2875 of file vehicle.cpp.

2878 {
2879  return vehicle::get_parts_at( pos.raw(), flag, condition );
2880 }

References get_parts_at(), and pos.

◆ get_parts_including_carried() [1/2]

vehicle_part_with_feature_range< std::string > vehicle::get_parts_including_carried ( std::string  feature) const

Yields a range of parts of this vehicle that each have the given feature and are not broken or removed.

The enabled status of the part is ignored.

Definition at line 3023 of file vehicle.cpp.

3025 {
3026  return vehicle_part_with_feature_range<std::string>( const_cast<vehicle &>( *this ),
3027  std::move( feature ), part_status_flag::working );
3028 }

References feature(), and working.

Referenced by init_state(), and map::process_items_in_vehicle().

◆ get_parts_including_carried() [2/2]

vehicle_part_with_feature_range< vpart_bitflags > vehicle::get_parts_including_carried ( vpart_bitflags  f) const

Definition at line 3030 of file vehicle.cpp.

3032 {
3033  return vehicle_part_with_feature_range<vpart_bitflags>( const_cast<vehicle &>( *this ), feature,
3035 }

References feature(), and working.

◆ get_passenger()

Character * vehicle::get_passenger ( int  you) const

Definition at line 3403 of file vehicle.cpp.

3404 {
3405  you = part_with_feature( you, VPFLAG_BOARDABLE, false );
3406  if( you >= 0 && parts[you].has_flag( vp_flag::passenger_flag ) ) {
3407  return g->critter_by_id<Character>( parts[you].passenger_id );
3408  }
3409  return nullptr;
3410 }

References g, part_with_feature(), parts, passenger_flag, and VPFLAG_BOARDABLE.

Referenced by act_on_map(), calc_mass_center(), npc::execute_action(), vpart_reference::get_passenger(), is_passenger(), part_vpower_w(), and split_vehicles().

◆ get_points()

const std::set< tripoint > & vehicle::get_points ( bool  force_refresh = false,
bool  no_fake = false 
) const

Definition at line 7725 of file vehicle.cpp.

7726 {
7727  if( force_refresh || occupied_cache_pos != global_pos3() ||
7731  occupied_points.clear();
7732  for( const std::pair<const point, std::vector<int>> &part_location : relative_parts ) {
7733  if( no_fake && part( part_location.second.front() ).is_fake ) {
7734  continue;
7735  }
7736  occupied_points.insert( global_part_pos3( part_location.second.front() ) );
7737  }
7738  }
7739 
7740  return occupied_points;
7741 }
units::angle occupied_cache_direction
Definition: vehicle.h:2116
std::set< tripoint > occupied_points
Definition: vehicle.h:2118

References tileray::dir(), face, global_part_pos3(), global_pos3(), vehicle_part::is_fake, occupied_cache_direction, occupied_cache_pos, occupied_points, part(), and relative_parts.

Referenced by map::add_vehicle_to_map(), Creature::auto_find_hostile_target(), check_falling_or_floating(), check_heli_ascend(), check_heli_descend(), game::control_vehicle(), map::detach_vehicle(), map::draw_maptile(), get_bounding_box(), overmap_ui::get_overmap_path_to(), map::memory_clear_vehicle_points(), map::move_vehicle(), MapExtras::mx_burned_ground(), part_collision(), veh_app_interact::refill(), veh_app_interact::remove(), sees_veh(), veh_interact::serialize_activity(), stop(), and vehicle_activity().

◆ get_printable_fuel_types()

std::vector< itype_id > vehicle::get_printable_fuel_types ( ) const

Returns an array of fuel types that can be printed.

Returns
An array of printable fuel type ids

Definition at line 313 of file vehicle_display.cpp.

314 {
315  std::set<itype_id> opts;
316  for( const vpart_reference &vpr : get_all_parts() ) {
317  const vehicle_part &pt = vpr.part();
318  if( !pt.has_flag( vp_flag::carried_flag ) && pt.is_fuel_store() &&
319  !pt.ammo_current().is_null() ) {
320  opts.emplace( pt.ammo_current() );
321  }
322  }
323 
324  std::vector<itype_id> res( opts.begin(), opts.end() );
325 
326  std::sort( res.begin(), res.end(), [&]( const itype_id & lhs, const itype_id & rhs ) {
327  return basic_consumption( rhs ) < basic_consumption( lhs );
328  } );
329 
330  return res;
331 }
bool is_null() const
Returns whether this represents the id of the null-object (in which case it's the null-id).
Definition: string_id.h:322

References vehicle_part::ammo_current(), carried_flag, get_all_parts(), vehicle_part::has_flag(), vehicle_part::is_fuel_store(), and string_id< T >::is_null().

Referenced by veh_app_interact::draw_info(), veh_app_interact::init_ui_windows(), veh_interact::move_fuel_cursor(), and print_fuel_indicators().

◆ get_remote_part()

std::optional< vpart_reference > vehicle::get_remote_part ( const vehicle_part vp_local) const

Get the remote vehicle and part that a part is targeting.

Useful for, e.g. power cables that have a vehicle part on both sides.

Parameters
vp_localVehicle part that is connected to the remote part.

Definition at line 6950 of file vehicle.cpp.

6951 {
6952  vehicle *veh = find_vehicle( tripoint_abs_ms( vp_local.target.second ) );
6953  // If the target vehicle is still there, ask it to remove its part
6954  if( veh != nullptr ) {
6955  const tripoint local_abs = get_map().getabs( global_part_pos3( vp_local ) );
6956  for( const int remote_partnum : veh->loose_parts ) {
6957  if( veh->parts[remote_partnum].target.first == local_abs &&
6958  veh->parts[remote_partnum].info().has_flag( VPFLAG_POWER_TRANSFER ) ) {
6959  return vpart_reference( *veh, remote_partnum );
6960  }
6961  }
6962  }
6963  return std::nullopt;
6964 }

References find_vehicle(), get_map(), map::getabs(), global_part_pos3(), loose_parts, parts, vehicle_part::target, and VPFLAG_POWER_TRANSFER.

Referenced by part_to_item(), remove_remote_part(), and shed_loose_parts().

◆ get_riders()

std::vector< rider_data > vehicle::get_riders ( ) const

Definition at line 3373 of file vehicle.cpp.

3374 {
3375  std::vector<rider_data> res;
3376  creature_tracker &creatures = get_creature_tracker();
3377  for( const vpart_reference &vp : get_avail_parts( VPFLAG_BOARDABLE ) ) {
3378  Creature *rider = creatures.creature_at( vp.pos() );
3379  if( rider ) {
3380  rider_data r;
3381  r.prt = vp.part_index();
3382  r.psg = rider;
3383  res.emplace_back( r );
3384  }
3385  }
3386  return res;
3387 }
int prt
Definition: vehicle.h:88
Creature * psg
Definition: vehicle.h:87

References creature_tracker::creature_at(), get_avail_parts(), get_creature_tracker(), rider_data::prt, rider_data::psg, and VPFLAG_BOARDABLE.

Referenced by map::displace_vehicle(), and map::shake_vehicle().

◆ get_safe_reference()

safe_reference< vehicle > vehicle::get_safe_reference ( )

Return a pointer-like type that's automatically invalidated if this item is destroyed or assigned-to.

Definition at line 248 of file vehicle.cpp.

249 {
250  return anchor.reference_to( this );
251 }
safe_reference< T > reference_to(T *object)
safe_reference_anchor anchor
Definition: vehicle.h:2233

References anchor, and safe_reference_anchor::reference_to().

Referenced by item::link_to(), and item::process_link().

◆ get_tools() [1/2]

const std::vector< item > & vehicle::get_tools ( const vehicle_part vp) const

Definition at line 5932 of file vehicle.cpp.

5933 {
5934  return vp.tools;
5935 }

References vehicle_part::tools.

◆ get_tools() [2/2]

std::vector< item > & vehicle::get_tools ( vehicle_part vp)

Definition at line 5927 of file vehicle.cpp.

5928 {
5929  return vp.tools;
5930 }

References vehicle_part::tools.

Referenced by calc_mass_center(), vehicles::finalize_prototypes(), and vehicle_prototype::save_vehicle_as_prototype().

◆ get_tow_part()

int vehicle::get_tow_part ( ) const

Definition at line 6782 of file vehicle.cpp.

6783 {
6784  for( const vpart_reference &vpr : this->get_any_parts( "TOW_CABLE" ) ) {
6785  return vpr.part_index();
6786  }
6787  return -1;
6788 }

References get_any_parts().

Referenced by do_towing_move(), has_tow_attached(), invalidate_towing(), no_towing_slack(), serialize(), set_tow_directions(), static_drag(), and tow_cable_too_far().

◆ get_z_change()

int vehicle::get_z_change ( ) const

Definition at line 4407 of file vehicle.cpp.

4408 {
4409  return requested_z_change;
4410 }

References requested_z_change.

◆ global_omt_location()

tripoint_abs_omt vehicle::global_omt_location ( ) const

Definition at line 3426 of file vehicle.cpp.

3427 {
3428  return project_to<coords::omt>( global_square_location() );
3429 }

References global_square_location().

Referenced by overmapbuffer::add_vehicle(), overmap_ui::get_overmap_path_to(), overmapbuffer::remove_vehicle(), and total_wind_epower().

◆ global_part_pos3() [1/2]

tripoint vehicle::global_part_pos3 ( const int &  index) const

Get the coordinates of the studied part of the vehicle.

Definition at line 3442 of file vehicle.cpp.

3443 {
3444  return global_part_pos3( parts[ index ] );
3445 }

References parts.

Referenced by add_item(), map::add_vehicle_to_cache(), automatic_fire_turret(), backfire(), break_off(), map::build_seen_cache(), can_close(), can_use_rails(), check_falling_or_floating(), veh_interact::complete_vehicle(), control_doors(), damage_direct(), map::displace_vehicle(), do_remove_part_actual(), do_towing_move(), map::do_vehicle_caching(), drain(), engine_cold_factor(), npc::execute_action(), explode_fuel(), find_vehicles_to_rack(), map::generate_lightmap(), get_monster(), get_points(), get_remote_part(), vehicle_part::get_targeting_npc(), game::grabbed_veh_move(), idle(), turret_data::in_range(), invalidate_towing(), leak_fuel(), level_vehicle(), merge_rackable_vehicle(), merge_vehicle_parts(), target_handler::mode_turrets(), map::move_vehicle(), no_towing_slack(), item_location::impl::item_on_vehicle::obtain_cost(), operate_scoop(), veh_app_interact::plug(), vpart_position::pos(), item_location::impl::item_on_vehicle::position(), power_parts(), put_into_vehicle(), refresh(), refresh_zones(), remove_carried_vehicle(), remove_part(), DefaultRemovePartHandler::removed(), serialize(), serialize_liquid_source(), serialize_liquid_target(), map::shake_vehicle(), shed_loose_parts(), slow_leak(), split_vehicles(), start_engine(), static_drag(), stop_engines(), total_solar_epower(), total_water_wheel_epower(), total_wind_epower(), tow_cable_too_far(), turrets_aim(), turrets_aim_and_fire(), turrets_set_mode(), turrets_set_targeting(), unboard_all(), update_time(), target_ui::update_turrets_in_range(), vehicle_caching_internal(), vehicle_caching_internal_above(), map::vehicle_vehicle_collision(), and map::vehicle_wheel_traction().

◆ global_part_pos3() [2/2]

tripoint vehicle::global_part_pos3 ( const vehicle_part pt) const

Definition at line 3447 of file vehicle.cpp.

3448 {
3449  return global_pos3() + pt.precalc[ 0 ];
3450 }

References global_pos3(), and vehicle_part::precalc.

◆ global_pos3()

tripoint vehicle::global_pos3 ( ) const

◆ global_square_location()

tripoint_abs_ms vehicle::global_square_location ( ) const

◆ ground_acceleration()

int vehicle::ground_acceleration ( bool  fueled = true,
int  at_vel_in_vmi = -1 
) const

Definition at line 3752 of file vehicle.cpp.

3753 {
3754  if( !( engine_on || skidding ) ) {
3755  return 0;
3756  }
3757  int target_vmiph = std::max( at_vel_in_vmi, std::max( 1000, max_velocity( fueled ) / 4 ) );
3758  int cmps = vmiph_to_cmps( target_vmiph );
3759  double weight = to_kilogram( total_mass() );
3760  if( is_towing() ) {
3761  vehicle *other_veh = tow_data.get_towed();
3762  if( other_veh ) {
3763  weight = weight + to_kilogram( other_veh->total_mass() );
3764  }
3765  }
3766  int engine_power_ratio = units::to_watt( total_power( fueled ) ) / weight;
3767  int accel_at_vel = 100 * 100 * engine_power_ratio / cmps;
3768  add_msg_debug( debugmode::DF_VEHICLE, "%s: accel at %d vimph is %d", name, target_vmiph,
3769  cmps_to_vmiph( accel_at_vel ) );
3770  return cmps_to_vmiph( accel_at_vel );
3771 }
bool is_towing() const
Definition: vehicle.cpp:6752
int cmps_to_vmiph(int cmps)
int vmiph_to_cmps(int vmiph)

References add_msg_debug, cmps_to_vmiph(), debugmode::DF_VEHICLE, engine_on, towing_data::get_towed(), is_towing(), max(), max_velocity(), name, skidding, units::to_kilogram(), units::to_watt(), total_mass(), total_power(), tow_data, and vmiph_to_cmps().

Referenced by acceleration(), and veh_interact::display_stats().

◆ handle_potential_theft()

bool vehicle::handle_potential_theft ( Character const &  you,
bool  check_only = false,
bool  prompt = true 
)

Definition at line 4686 of file vehicle.cpp.

4687 {
4688  const bool is_owned_by_player =
4689  is_owned_by( you ) || ( you.is_npc() && is_owned_by( get_avatar() ) &&
4690  you.as_npc()->is_friendly( get_avatar() ) );
4691  // the vehicle is yours, that's fine.
4692  if( is_owned_by_player ) {
4693  return true;
4694  }
4695  std::vector<Creature *> witnesses = g->get_creatures_if( [&you, this]( Creature const & cr ) {
4696  Character const *const elem = cr.as_character();
4697  return elem != nullptr && you.getID() != elem->getID() && is_owned_by( *elem ) &&
4698  rl_dist( elem->pos(), you.pos() ) < MAX_VIEW_DISTANCE && elem->sees( you.pos() );
4699  } );
4700  if( !has_owner() || ( witnesses.empty() && ( has_old_owner() || you.is_npc() ) ) ) {
4701  if( !has_owner() ||
4702  // if there is a marker for having been stolen, but 15 minutes have passed, then
4703  // officially transfer ownership
4704  ( theft_time && calendar::turn - *theft_time > 15_minutes ) ) {
4705  set_owner( you.get_faction()->id );
4706  remove_old_owner();
4707  }
4708  // No witnesses? then don't need to prompt, we assume the player is in process of stealing it.
4709  // Ownership transfer checking is handled above, and warnings handled below.
4710  // This is just to perform interaction with the vehicle without a prompt.
4711  // It will prompt first-time, even with no witnesses, to inform player it is owned by someone else
4712  // subsequently, no further prompts, the player should know by then.
4713  return true;
4714  }
4715  // if we are just checking if we could continue without problems, then the rest is assumed false
4716  if( check_only ) {
4717  return false;
4718  }
4719  // if we got here, there's some theft occurring
4720  if( prompt ) {
4721  if( !you.query_yn(
4722  _( "This vehicle belongs to: %s, there may be consequences if you are observed interacting with it, continue?" ),
4723  _( get_owner_name() ) ) ) {
4724  return false;
4725  }
4726  }
4727  // set old owner so that we can restore ownership if there are witnesses.
4728  set_old_owner( get_owner() );
4729  bool const make_angry = !witnesses.empty() && you.add_faction_warning( get_owner() );
4730  for( Creature *elem : witnesses ) {
4731  if( elem->is_npc() ) {
4732  npc &n = *elem->as_npc();
4733  n.say( "<witnessed_thievery>", 7 );
4734  if( make_angry ) {
4735  n.make_angry();
4736  }
4737  }
4738  // remove the temporary marker for a successful theft, as it was witnessed.
4739  remove_old_owner();
4740  }
4741  // if we got here, then the action will proceed after the previous warning
4742  return true;
4743 }
bool is_npc() const override
Definition: character.h:538
virtual Character * as_character()
Definition: creature.h:274
virtual npc * as_npc()
Definition: creature.h:286
void say(const char *const line, Args &&... args) const
Definition: npc.h:1025
void make_angry()
Definition: npc.cpp:1626
faction_id get_owner() const
Definition: vehicle.h:977
bool has_old_owner() const
Definition: vehicle.h:986
bool is_owned_by(const Character &c, bool available_to_take=false) const
Definition: vehicle.cpp:4644
bool has_owner() const
Definition: vehicle.h:983
std::string get_owner_name() const
Definition: vehicle.cpp:4668
void set_old_owner(const faction_id &temp_owner)
Definition: vehicle.h:965
void remove_old_owner()
Definition: vehicle.h:969
void set_owner(const faction_id &new_owner)
Definition: vehicle.h:973
constexpr int MAX_VIEW_DISTANCE
@ prompt
Definition: pickup.h:42

References _, Character::add_faction_warning(), Creature::as_character(), Creature::as_npc(), npc::as_npc(), g, get_avatar(), Character::get_faction(), get_owner(), get_owner_name(), Character::getID(), has_old_owner(), has_owner(), faction_template::id, npc::is_friendly(), Character::is_npc(), is_owned_by(), npc::make_angry(), MAX_VIEW_DISTANCE, Creature::pos(), Pickup::prompt, Character::query_yn(), remove_old_owner(), rl_dist(), npc::say(), Character::sees(), set_old_owner(), set_owner(), theft_time, and calendar::turn.

Referenced by doors::close_door(), game::control_vehicle(), veh_interact::do_main_loop(), game::grabbed_veh_move(), doors::lock_door(), avatar_action::move(), open(), veh_menu::query(), smash(), and doors::unlock_door().

◆ handle_trap()

void vehicle::handle_trap ( const tripoint p,
vehicle_part vp_wheel 
)

Definition at line 1218 of file vehicle_move.cpp.

1219 {
1220  if( !vp_wheel.info().has_flag( VPFLAG_WHEEL ) ) {
1221  debugmsg( "vehicle::handle_trap called on non-WHEEL part" );
1222  return;
1223  }
1224  map &here = get_map();
1225  const trap &tr = here.tr_at( p );
1226 
1227  if( tr.is_null() ) {
1228  // If the trap doesn't exist, we can't interact with it, so just return
1229  return;
1230  }
1231  const vehicle_handle_trap_data &veh_data = tr.vehicle_data;
1232 
1233  if( veh_data.is_falling ) {
1234  return;
1235  }
1236 
1237  Character &player_character = get_player_character();
1238  const bool seen = player_character.sees( p );
1239  const bool known = tr.can_see( p, player_character );
1240  const bool damage_done = vp_wheel.info().durability <= veh_data.damage;
1241  if( seen && damage_done ) {
1242  if( known ) {
1243  //~ %1$s: name of the vehicle; %2$s: name of the related vehicle part; %3$s: trap name
1244  add_msg( m_bad, _( "The %1$s's %2$s runs over %3$s." ), name, vp_wheel.name(), tr.name() );
1245  } else {
1246  add_msg( m_bad, _( "The %1$s's %2$s runs over something." ), name, vp_wheel.name() );
1247  }
1248  }
1249 
1250  if( veh_data.chance >= rng( 1, 100 ) ) {
1251  if( veh_data.sound_volume > 0 ) {
1252  sounds::sound( p, veh_data.sound_volume, sounds::sound_t::combat, veh_data.sound, false,
1253  veh_data.sound_type, veh_data.sound_variant );
1254  }
1255  if( veh_data.do_explosion ) {
1256  const Creature *source = player_in_control( player_character ) ? &player_character : nullptr;
1257  explosion_handler::explosion( source, p, veh_data.damage, 0.5f, false, veh_data.shrapnel );
1258  // Don't damage wheels with very high durability, such as roller drums or rail wheels
1259  } else if( damage_done ) {
1260  // Hit the wheel directly since it ran right over the trap.
1261  damage_direct( here, vp_wheel, veh_data.damage );
1262  }
1263  bool still_has_trap = true;
1264  if( veh_data.remove_trap || veh_data.do_explosion ) {
1265  here.remove_trap( p );
1266  still_has_trap = false;
1267  }
1268  for( const auto &it : veh_data.spawn_items ) {
1269  int cnt = roll_remainder( it.second );
1270  if( cnt > 0 ) {
1271  here.spawn_item( p, it.first, cnt );
1272  }
1273  }
1274  if( veh_data.set_trap ) {
1275  here.trap_set( p, veh_data.set_trap.id() );
1276  still_has_trap = true;
1277  }
1278  if( still_has_trap ) {
1279  const trap &tr = here.tr_at( p );
1280  if( seen || known ) {
1281  // known status has been reset by map::trap_set()
1282  player_character.add_known_trap( p, tr );
1283  }
1284  if( seen && !known ) {
1285  // hard to miss!
1286  const std::string direction = direction_name( direction_from( player_character.pos(), p ) );
1287  add_msg( _( "You've spotted a %1$s to the %2$s!" ), tr.name(), direction );
1288  }
1289  }
1290  }
1291 }
void add_known_trap(const tripoint &pos, const trap &t)
const trap & tr_at(const tripoint &p) const
Definition: map.cpp:6213
void spawn_item(const tripoint &p, const itype_id &type_id, unsigned quantity=1, int charges=0, const time_point &birthday=calendar::start_of_cataclysm, int damlevel=0, const std::set< flag_id > &flags={}, const std::string &variant="", const std::string &faction="")
Definition: map.cpp:5100
void trap_set(const tripoint &p, const trap_id &type)
Definition: map.cpp:6297
void remove_trap(const tripoint &p)
Definition: map.cpp:6338
int_id< T > id() const
Translate the string based it to the matching integer based id.
Definition: ammo_effect.cpp:54
direction direction_from(const coords::coord_point< Point, Origin, Scale, LhsInBounds > &loc1, const coords::coord_point< Point, Origin, Scale, RhsInBounds > &loc2)
Definition: coordinates.h:790
std::string direction_name(const direction dir)
Definition: line.cpp:612
Some traps aren't actually traps in the usual sense of the word.
Definition: trap.h:109
std::string name() const
Definition: trap.cpp:228
vehicle_handle_trap_data vehicle_data
Definition: trap.h:167
bool is_null() const
Whether this is the null-traps, aka no trap at all.
Definition: trap.cpp:366
bool can_see(const tripoint &pos, const Character &p) const
Can player/npc p see this kind of trap, either by their memory (they known there is the trap) or by t...
Definition: trap.cpp:320
translation sound
Definition: trap.h:79
std::string sound_variant
Definition: trap.h:81
std::vector< std::pair< itype_id, double > > spawn_items
Definition: trap.h:83
std::string sound_type
Definition: trap.h:80
trap_str_id set_trap
Definition: trap.h:84
@ VPFLAG_WHEEL
Definition: veh_type.h:79

References _, Character::add_known_trap(), add_msg(), trap::can_see(), vehicle_handle_trap_data::chance, sounds::combat, vehicle_handle_trap_data::damage, damage_direct(), debugmsg, direction_from(), direction_name(), vehicle_handle_trap_data::do_explosion, vpart_info::durability, explosion_handler::explosion(), get_map(), get_player_character(), vpart_info::has_flag(), string_id< T >::id(), vehicle_part::info(), vehicle_handle_trap_data::is_falling, trap::is_null(), m_bad, trap::name(), vehicle_part::name(), name, player_in_control(), Creature::pos(), map::remove_trap(), vehicle_handle_trap_data::remove_trap, rng(), roll_remainder(), Character::sees(), vehicle_handle_trap_data::set_trap, vehicle_handle_trap_data::shrapnel, sounds::sound(), vehicle_handle_trap_data::sound, vehicle_handle_trap_data::sound_type, vehicle_handle_trap_data::sound_variant, vehicle_handle_trap_data::sound_volume, map::spawn_item(), vehicle_handle_trap_data::spawn_items, map::tr_at(), map::trap_set(), trap::vehicle_data, and VPFLAG_WHEEL.

Referenced by game::grabbed_veh_move(), and map::move_vehicle().

◆ handling_difficulty()

float vehicle::handling_difficulty ( ) const

Returns roughly driving skill level at which there is no chance of fumbling.

Definition at line 4807 of file vehicle.cpp.

4808 {
4809  const float steer = std::max( 0.0f, steering_effectiveness() );
4810  const float ktraction = k_traction( get_map().vehicle_wheel_traction( *this ) );
4811  const float aligned = std::max( 0.0f, 1.0f - ( face_vec() - dir_vec() ).magnitude() );
4812 
4813  // TestVehicle: perfect steering, moving on road at 100 mph (25 tiles per turn) = 0.0
4814  // TestVehicle but on grass (0.75 friction) = 2.5
4815  // TestVehicle but with bad steering (0.5 steer) = 5
4816  // TestVehicle but on fungal bed (0.5 friction) and bad steering = 10
4817  // TestVehicle but turned 90 degrees during this turn (0 align) = 10
4818  const float diff_mod = ( 1.0f - steer ) + ( 1.0f - ktraction ) + ( 1.0f - aligned );
4819  return velocity * diff_mod / vehicles::vmiph_per_tile;
4820 }
rl_vec2d dir_vec() const
float steering_effectiveness() const
Definition: vehicle.cpp:4769

References dir_vec(), face_vec(), get_map(), k_traction(), max(), steering_effectiveness(), velocity, and vehicles::vmiph_per_tile.

Referenced by pldrive(), and selfdrive().

◆ has_available_electric_engine()

bool vehicle::has_available_electric_engine ( )

Definition at line 5785 of file vehicle.cpp.

5786 {
5787  for( const int p : engines ) {
5788  const vehicle_part &vp = parts[p];
5789  if( is_engine_type( vp, fuel_type_battery ) && ( vp.is_available() || vp.enabled ) ) {
5790  return true;
5791  }
5792  }
5793  return false;
5794 }
bool is_engine_type(const vehicle_part &vp, const itype_id &ft) const
Definition: vehicle.cpp:1000

References vehicle_part::enabled, engines, fuel_type_battery, vehicle_part::is_available(), is_engine_type(), and parts.

Referenced by disable_smart_controller_if_needed(), and install_part().

◆ has_engine_conflict()

std::optional< std::string > vehicle::has_engine_conflict ( const vpart_info possible_conflict) const

Definition at line 978 of file vehicle.cpp.

979 {
980  if( !possible_conflict.engine_info ) {
981  return std::nullopt; // not an engine
982  }
983  const std::vector<std::string> &new_excludes = possible_conflict.engine_info->exclusions;
984  if( new_excludes.empty() ) {
985  return std::nullopt;
986  }
987  for( const int p : engines ) {
988  const vehicle_part &vp = parts[p];
989  std::vector<std::string> install_excludes = vp.info().engine_info->exclusions;
990  std::vector<std::string> conflicts;
991  std::set_intersection( new_excludes.begin(), new_excludes.end(), install_excludes.begin(),
992  install_excludes.end(), back_inserter( conflicts ) );
993  if( !conflicts.empty() ) {
994  return conflicts.front();
995  }
996  }
997  return std::nullopt;
998 }

References vpart_info::engine_info, engines, vehicle_part::info(), and parts.

Referenced by can_mount(), and veh_interact::update_part_requirements().

◆ has_engine_type()

bool vehicle::has_engine_type ( const itype_id ft,
bool  enabled 
) const

Definition at line 957 of file vehicle.cpp.

958 {
959  for( const int p : engines ) {
960  const vehicle_part &vp = parts[p];
961  if( is_engine_type( vp, ft ) && ( !enabled || is_engine_on( vp ) ) ) {
962  return true;
963  }
964  }
965  return false;
966 }

References enabled, engines, is_engine_on(), is_engine_type(), and parts.

Referenced by assign_veh_to_follow(), game::chat(), game::control_vehicle(), max_reverse_velocity(), player_in_control(), pldrive(), tell_veh_stop_following(), and thrust().

◆ has_engine_type_not()

bool vehicle::has_engine_type_not ( const itype_id ft,
bool  enabled 
) const

Definition at line 967 of file vehicle.cpp.

968 {
969  for( const int p : engines ) {
970  const vehicle_part &vp = parts[p];
971  if( !is_engine_type( vp, ft ) && ( !enabled || is_engine_on( vp ) ) ) {
972  return true;
973  }
974  }
975  return false;
976 }

References enabled, engines, is_engine_on(), is_engine_type(), and parts.

Referenced by build_interact_menu(), idle(), and init_state().

◆ has_old_owner()

bool vehicle::has_old_owner ( ) const
inline

Definition at line 986 of file vehicle.h.

986  {
987  return !old_owner.is_null();
988  }

References string_id< T >::is_null(), and old_owner.

Referenced by handle_potential_theft().

◆ has_owner()

bool vehicle::has_owner ( ) const
inline

◆ has_part() [1/2]

bool vehicle::has_part ( const std::string &  flag,
bool  enabled = false 
) const

Check if vehicle has at least one unbroken part with specified flag.

Parameters
flagSpecified flag to search parts for
enabledif set part must also be enabled to be considered
Returns
true if part is found

Definition at line 2827 of file vehicle.cpp.

2828 {
2829  for( const vpart_reference &vpr : get_all_parts() ) {
2830  if( !vpr.part().removed && ( !enabled || vpr.part().enabled ) && !vpr.part().is_broken() &&
2831  vpr.part().info().has_flag( flag ) ) {
2832  return true;
2833  }
2834  }
2835  return false;
2836 }

References enabled, and get_all_parts().

Referenced by build_electronics_menu(), build_interact_menu(), veh_interact::can_remove_part(), veh_interact::do_repair(), liquid_handler::get_liquid_target(), idle(), install_part(), on_move(), map::process_items_in_vehicle(), refresh(), selfdrive(), start_engine(), turrets_set_targeting(), and veh_interact::update_part_requirements().

◆ has_part() [2/2]

bool vehicle::has_part ( const tripoint pos,
const std::string &  flag,
bool  enabled = false 
) const

Check if vehicle has at least one unbroken part with specified flag.

Parameters
poslimit check for parts to this global position
flagThe specified flag
enabledif set part must also be enabled to be considered

Definition at line 2838 of file vehicle.cpp.

2839 {
2840  const tripoint relative_pos = pos - global_pos3();
2841 
2842  for( const vpart_reference &vpr : get_all_parts() ) {
2843  if( vpr.part().precalc[0] != relative_pos ) {
2844  continue;
2845  }
2846  if( !vpr.part().removed && ( !enabled || vpr.part().enabled ) && !vpr.part().is_broken() &&
2847  vpr.part().info().has_flag( flag ) ) {
2848  return true;
2849  }
2850  }
2851  return false;
2852 }

References enabled, get_all_parts(), global_pos3(), and pos.

◆ has_security_working()

bool vehicle::has_security_working ( ) const

Definition at line 1038 of file vehicle.cpp.

1039 {
1040  if( fuel_left( fuel_type_battery ) > 0 ) {
1041  for( const int s : speciality ) {
1042  const vehicle_part &vp = part( s );
1043  if( vp.info().has_flag( "SECURITY" ) && vp.is_available() ) {
1044  return true;
1045  }
1046  }
1047  }
1048  return false;
1049 }
std::vector< int > speciality
Definition: vehicle.h:2188

References fuel_left(), fuel_type_battery, vpart_info::has_flag(), vehicle_part::info(), vehicle_part::is_available(), part(), and speciality.

Referenced by alarm(), build_interact_menu(), hotwire_car_activity_actor::finish(), and hackveh().

◆ has_structural_part()

bool vehicle::has_structural_part ( const point dp) const
private

Definition at line 1153 of file vehicle.cpp.

1154 {
1155  for( const int elem : parts_at_relative( dp, false ) ) {
1156  const vehicle_part &vp = part( elem );
1157  const vpart_info &vpi = vp.info();
1158  if( vpi.location == part_location_structure &&
1160  !vpi.has_flag( "PROTRUSION" ) ) {
1161  return true;
1162  }
1163  }
1164  return false;
1165 }

References carried_flag, vpart_info::has_flag(), vehicle_part::has_flag(), vehicle_part::info(), vpart_info::location, part(), part_location_structure(), and parts_at_relative().

Referenced by can_mount().

◆ has_sufficient_rotorlift()

bool vehicle::has_sufficient_rotorlift ( ) const

Definition at line 4385 of file vehicle.cpp.

4386 {
4387  // comparison of newton to newton - convert kg to newton.
4388  return lift_thrust_of_rotorcraft( true ) > to_kilogram( total_mass() ) * 9.8;
4389 }
double lift_thrust_of_rotorcraft(bool fuelled, bool safe=false) const
is the vehicle flying? is it a rotorcraft?
Definition: vehicle.cpp:4366

References lift_thrust_of_rotorcraft(), units::to_kilogram(), and total_mass().

Referenced by is_rotorcraft().

◆ has_tag()

bool vehicle::has_tag ( const std::string &  tag) const

Definition at line 8322 of file vehicle.cpp.

8323 {
8324  return tags.count( tag ) > 0;
8325 }

References tags.

Referenced by construct::check_no_wiring(), is_appliance(), is_powergrid(), place_appliance(), and refresh().

◆ has_tow_attached()

bool vehicle::has_tow_attached ( ) const

Definition at line 6790 of file vehicle.cpp.

6791 {
6792  return get_tow_part() != -1;
6793 }

References get_tow_part().

Referenced by item::link_to().

◆ honk_horn()

void vehicle::honk_horn ( ) const

Definition at line 840 of file vehicle_use.cpp.

841 {
842  const bool no_power = !fuel_left( fuel_type_battery );
843  bool honked = false;
844 
845  for( const vpart_reference &vp : get_avail_parts( "HORN" ) ) {
846  //Only bicycle horn doesn't need electricity to work
847  const vpart_info &horn_type = vp.info();
848  if( ( horn_type.id != vpart_horn_bicycle ) && no_power ) {
849  continue;
850  }
851  if( !honked ) {
852  add_msg( _( "You honk the horn!" ) );
853  honked = true;
854  }
855  //Get global position of horn
856  const tripoint horn_pos = vp.pos();
857  //Determine sound
858  if( horn_type.bonus >= 110 ) {
859  //~ Loud horn sound
860  sounds::sound( horn_pos, horn_type.bonus, sounds::sound_t::alarm, _( "HOOOOORNK!" ), false,
861  "vehicle", "horn_loud" );
862  } else if( horn_type.bonus >= 80 ) {
863  //~ Moderate horn sound
864  sounds::sound( horn_pos, horn_type.bonus, sounds::sound_t::alarm, _( "BEEEP!" ), false, "vehicle",
865  "horn_medium" );
866  } else {
867  //~ Weak horn sound
868  sounds::sound( horn_pos, horn_type.bonus, sounds::sound_t::alarm, _( "honk." ), false, "vehicle",
869  "horn_low" );
870  }
871  }
872 
873  if( !honked ) {
874  add_msg( _( "You honk the horn, but nothing happens." ) );
875  }
876 }
static const vpart_id vpart_horn_bicycle("horn_bicycle")

References _, add_msg(), sounds::alarm, vpart_info::bonus, fuel_left(), fuel_type_battery, get_avail_parts(), vpart_info::id, sounds::sound(), and vpart_horn_bicycle.

Referenced by build_interact_menu().

◆ idle()

void vehicle::idle ( bool  on_map)

Definition at line 5623 of file vehicle.cpp.

5624 {
5625  avg_velocity = ( velocity + avg_velocity ) / 2;
5626 
5627  power_parts();
5628  Character &player_character = get_player_character();
5629  if( engine_on && total_power() > 0_W ) {
5630  // Consume fuel at here only if the vehicle is not thrusting.
5631  // See the condition under which vehicle::thrust() is called in vehicle::gain_moves().
5632  if( !( ( player_in_control( player_character ) || is_following || is_patrolling ) &&
5633  cruise_velocity != 0 ) ) {
5634  int idle_rate = alternator_load;
5635  if( idle_rate < 10 ) {
5636  idle_rate = 10; // minimum idle is 1% of full throttle
5637  }
5638  if( has_engine_type_not( fuel_type_muscle, true ) ) {
5639  consume_fuel( idle_rate, true );
5640  }
5641 
5642  if( on_map ) {
5643  noise_and_smoke( idle_rate, 1_turns );
5644  }
5645  }
5646  } else {
5647  if( engine_on &&
5650  add_msg_if_player_sees( global_pos3(), _( "The %s's engine dies!" ), name );
5651  }
5652  engine_on = false;
5653  }
5654 
5655  if( !warm_enough_to_plant( player_character.pos() ) ) {
5656  for( int i : planters ) {
5657  vehicle_part &vp = parts[ i ];
5658  if( vp.enabled ) {
5659  add_msg_if_player_sees( global_pos3(), _( "The %s's planter turns off due to low temperature." ),
5660  name );
5661  vp.enabled = false;
5662  }
5663  }
5664  }
5665 
5668 
5669  if( !on_map ) {
5670  return;
5671  } else {
5673  }
5674 
5675  map &here = get_map();
5676  // Parts emitting fields
5677  const std::pair<int, double> exhaust_and_muffle = get_exhaust_part();
5678  for( const int emitter_idx : emitters ) {
5679  const vehicle_part &pt = parts[emitter_idx];
5680  if( pt.is_unavailable() || !pt.enabled ) {
5681  continue;
5682  }
5683  for( const emit_id &e : pt.info().emissions ) {
5684  here.emit_field( global_part_pos3( pt ), e );
5685  }
5686  for( const emit_id &e : pt.info().exhaust ) {
5687  if( exhaust_and_muffle.first == -1 ) {
5688  here.emit_field( global_part_pos3( pt ), e );
5689  } else {
5690  here.emit_field( exhaust_dest( exhaust_and_muffle.first ), e );
5691  }
5692  }
5693  }
5694 
5695  if( has_part( "STEREO", true ) ) {
5696  play_music();
5697  }
5698 
5699  if( has_part( "CHIMES", true ) ) {
5700  play_chimes();
5701  }
5702 
5703  if( has_part( "CRASH_TERRAIN_AROUND", true ) ) {
5705  }
5706 
5707  if( is_alarm_on ) {
5708  alarm();
5709  }
5710 
5711  // Notify player about status of all turrets if they're at controls
5712  bool player_at_controls = !get_parts_at( player_character.pos(), "CONTROLS",
5713  part_status_flag::working ).empty();
5714 
5715  for( vehicle_part *turret : turrets() ) {
5716  item_location base = turret_query( *turret ).base();
5717  // Notify player about status of a turret if they're on the same tile
5718  if( player_at_controls || player_character.pos() == base.position() ) {
5719  base->process( here, &player_character, base.position() );
5720  } else {
5721  base->process( here, nullptr, base.position() );
5722  }
5723  }
5724 }
tripoint position() const
Returns the position where the item is found.
bool process(map &here, Character *carrier, const tripoint &pos, float insulation=1, temperature_flag flag=temperature_flag::NORMAL, float spoil_multiplier_parent=1.0f, bool recursive=true)
This is called once each turn.
Definition: item.cpp:14010
void emit_field(const tripoint &pos, const emit_id &src, float mul=1.0f)
Runs one cycle of emission src which may result in propagation of fields.
Definition: map_field.cpp:2102
void crash_terrain_around()
void smart_controller_handle_turn(const std::optional< float > &k_traction_cache=std::nullopt)
if smart controller is enabled, turns on and off engines depending on load and battery level
void play_chimes() const
void update_time(const time_point &update_to)
Definition: vehicle.cpp:7876
units::power linked_item_epower_this_turn
Definition: vehicle.h:1477
void play_music() const
void consume_fuel(int load, bool idling)
Definition: vehicle.cpp:4864
int alternator_load
Definition: vehicle.h:2264
tripoint exhaust_dest(int part) const
Definition: vehicle.cpp:8306
void noise_and_smoke(int load, time_duration time=1_turns)
Generate noise or smoke from a vehicle with engines turned on load = how hard the engines are working...
Definition: vehicle.cpp:4018
void alarm()
std::vector< int > emitters
Definition: vehicle.h:2180
void power_parts()
Definition: vehicle.cpp:5236
std::vector< int > planters
Definition: vehicle.h:2194
std::pair< int, double > get_exhaust_part() const
Definition: vehicle.cpp:8290
std::set< emit_id > emissions
Emissions of part.
Definition: veh_type.h:367
std::set< emit_id > exhaust
Exhaust emissions of part.
Definition: veh_type.h:375
static const itype_id fuel_type_wind("wind")

References _, add_msg_if_player_sees(), alarm(), alternator_load, avg_velocity, turret_data::base(), consume_fuel(), crash_terrain_around(), cruise_velocity, vpart_info::emissions, map::emit_field(), emitters, vehicle_part::enabled, engine_on, vpart_info::exhaust, exhaust_dest(), fuel_type_animal, fuel_type_mana, fuel_type_muscle, fuel_type_wind, get_exhaust_part(), get_map(), get_parts_at(), get_player_character(), global_part_pos3(), global_pos3(), has_engine_type_not(), has_part(), vehicle_part::info(), is_alarm_on, is_following, is_patrolling, vehicle_part::is_unavailable(), linked_item_epower_this_turn, name, noise_and_smoke(), parts, planters, play_chimes(), play_music(), player_in_control(), Creature::pos(), item_location::position(), power_parts(), item::process(), smart_controller_handle_turn(), total_power(), calendar::turn, turret_query(), turrets(), update_time(), velocity, warm_enough_to_plant(), and working.

◆ immediate_path()

std::set< point > vehicle::immediate_path ( const units::angle rotate = 0_degrees)

Definition at line 682 of file vehicle.cpp.

683 {
684  std::set<point> points_to_check;
685  const int distance_to_check = 10 + ( velocity / 800 );
686  units::angle adjusted_angle = normalize( face.dir() + rotate );
687  // clamp to multiples of 15.
688  adjusted_angle = round_to_multiple_of( adjusted_angle, vehicles::steer_increment );
689  tileray collision_vector;
690  collision_vector.init( adjusted_angle );
691  map &here = get_map();
692  point top_left_actual = global_pos3().xy() + coord_translate( front_left );
693  point top_right_actual = global_pos3().xy() + coord_translate( front_right );
694  std::vector<point> front_row = line_to( here.getabs( top_left_actual ),
695  here.getabs( top_right_actual ) );
696  for( const point &elem : front_row ) {
697  for( int i = 0; i < distance_to_check; ++i ) {
698  collision_vector.advance( i );
699  point point_to_add = elem + point( collision_vector.dx(), collision_vector.dy() );
700  points_to_check.emplace( point_to_add );
701  }
702  }
703  collision_check_points = points_to_check;
704  return points_to_check;
705 }
point front_right
Definition: vehicle.h:2307
point front_left
Definition: vehicle.h:2306
units::angle normalize(units::angle a, units::angle mod)
Given an angle, add or subtract multiples of 360_degrees until it's in the range [0,...
units::quantity< T, U > round_to_multiple_of(units::quantity< T, U > val, units::quantity< T, U > of)
Definition: units_utility.h:41

References tileray::advance(), collision_check_points, coord_translate(), tileray::dir(), tileray::dx(), tileray::dy(), face, front_left, front_right, get_map(), map::getabs(), global_pos3(), tileray::init(), line_to(), normalize(), point, rotate(), round_to_multiple_of(), vehicles::steer_increment, velocity, and tripoint::xy().

Referenced by precollision_check().

◆ index_of_part()

int vehicle::index_of_part ( const vehicle_part part,
bool  include_removed = false 
) const

Definition at line 3224 of file vehicle.cpp.

3225 {
3226  if( !part || ( !include_removed && part->removed ) ) {
3227  return -1;
3228  }
3229  for( size_t i = 0; i < parts.size(); i++ ) {
3230  if( &parts[i] == part ) {
3231  return static_cast<int>( i );
3232  }
3233  }
3234  return -1;
3235 }

References part(), parts, and vehicle_part::removed.

Referenced by turret_data::base(), break_off(), can_do_activity_there(), can_unmount(), damage_direct(), veh_interact::do_mend(), veh_interact::do_siphon(), part_vpower_w(), precollision_check(), veh_app_interact::refill(), veh_app_interact::remove(), remove_part(), veh_interact::select_part(), veh_interact::serialize_activity(), veh_app_interact::siphon(), vehicle_activity(), and would_repair_prevent_flyable().

◆ init_state()

void vehicle::init_state ( map placed_on,
int  init_veh_fuel,
int  init_veh_status 
)

Definition at line 292 of file vehicle.cpp.

293 {
294  // vehicle parts excluding engines in non-owned vehicles are by default turned off
295  for( vehicle_part &pt : parts ) {
296  pt.enabled = !has_owner() && pt.is_engine();
297  }
298 
299  bool destroySeats = false;
300  bool destroyControls = false;
301  bool destroyTank = false;
302  bool destroyEngine = false;
303  bool destroyTires = false;
304  bool blood_covered = false;
305  bool blood_inside = false;
306  bool has_no_key = false;
307  bool destroyAlarm = false;
308 
309  // More realistically it should be -5 days old
311 
312  if( get_option<bool>( "OVERRIDE_VEHICLE_INIT_STATE" ) ) {
313  init_veh_status = get_option<int>( "VEHICLE_STATUS_AT_SPAWN" );
314  init_veh_fuel = get_option<int>( "VEHICLE_FUEL_AT_SPAWN" );
315  }
316 
317  std::map<itype_id, double> fuels; // lets tanks of same fuel type have even contents
318  const auto rng_fuel_amount = [&fuels, init_veh_fuel]( vehicle_part & vp, const itype_id & fuel ) {
319  if( !fuel ) {
320  vp.ammo_unset(); // clear if no valid fuel
321  return;
322  }
323  const int max = vp.item_capacity( fuel );
324  if( init_veh_fuel < 0 ) {
325  // map.emplace(...).first returns iterator to the new or existing element
326  const double roll = fuels.emplace( fuel, normal_roll( 0.3, 0.15 ) ).first->second;
327  vp.ammo_set( fuel, max * std::clamp( roll, 0.05, 0.95 ) );
328  } else if( init_veh_fuel == 0 ) {
329  vp.ammo_unset();
330  } else if( init_veh_fuel > 0 && init_veh_fuel < 100 ) {
331  vp.ammo_set( fuel, max * init_veh_fuel / 100 );
332  } else { // init_veh_fuel >= 100
333  vp.ammo_set( fuel, max );
334  }
335  };
336  // veh_status is initial vehicle damage
337  // -1 = light damage (DEFAULT)
338  // 0 = undamaged
339  // 1 = disabled: destroyed seats, controls, tanks, tires, OR engine
340  // 2 = undamaged with no faults or security
341  int veh_status = -1;
342  if( init_veh_status == 0 ) {
343  veh_status = 0;
344  }
345  if( init_veh_status == 1 ) {
346  veh_status = 1;
347 
348  const int rand = rng( 1, 5 );
349  switch( rand ) {
350  case 1:
351  destroySeats = true;
352  break;
353  case 2:
354  destroyControls = true;
355  break;
356  case 3:
357  destroyTank = true;
358  break;
359  case 4:
360  destroyEngine = true;
361  break;
362  case 5:
363  destroyTires = true;
364  break;
365  }
366  }
367 
368  if( one_in( 3 ) ) {
369  //33% chance for a locked vehicle
370  has_no_key = true;
371  }
372 
373  if( !one_in( 3 ) ) {
374  //most cars should have a destroyed alarm
375  destroyAlarm = true;
376  }
377  // Make engine faults more likely
378  destroyEngine = destroyEngine || one_in( 3 );
379 
380  if( init_veh_status == 2 ) {
381  veh_status = 0;
382  has_no_key = false;
383  destroyAlarm = false;
384  destroyEngine = false;
385  }
386 
387  //Provide some variety to non-mint vehicles
388  if( veh_status != 0 ) {
389  //Leave engine running in some vehicles, if the engine has not been destroyed
390  //chance decays from 1 in 4 vehicles on day 0 to 1 in (day + 4) in the future.
391  int current_day = std::max( to_days<int>( calendar::turn - calendar::turn_zero ), 0 );
392  if( init_veh_fuel != 0 && !engines.empty() &&
393  one_in( current_day + 4 ) && !destroyEngine && !has_no_key &&
395  engine_on = true;
396  }
397 
398  bool light_head = one_in( 20 );
399  bool light_whead = one_in( 20 ); // wide-angle headlight
400  bool light_dome = one_in( 16 );
401  bool light_aisle = one_in( 8 );
402  bool light_hoverh = one_in( 4 ); // half circle overhead light
403  bool light_overh = one_in( 4 );
404  bool light_atom = one_in( 2 );
405  for( vehicle_part &vp : parts ) {
406  const vpart_info vpi = vp.info();
407  if( vpi.has_flag( VPFLAG_CONE_LIGHT ) ) {
408  vp.enabled = light_head;
409  } else if( vpi.has_flag( VPFLAG_WIDE_CONE_LIGHT ) ) {
410  vp.enabled = light_whead;
411  } else if( vpi.has_flag( VPFLAG_DOME_LIGHT ) ) {
412  vp.enabled = light_dome;
413  } else if( vpi.has_flag( VPFLAG_AISLE_LIGHT ) ) {
414  vp.enabled = light_aisle;
415  } else if( vpi.has_flag( VPFLAG_HALF_CIRCLE_LIGHT ) ) {
416  vp.enabled = light_hoverh;
417  } else if( vpi.has_flag( VPFLAG_CIRCLE_LIGHT ) ) {
418  vp.enabled = light_overh;
419  } else if( vpi.has_flag( VPFLAG_ATOMIC_LIGHT ) ) {
420  vp.enabled = light_atom;
421  }
422  }
423 
424  if( one_in( 10 ) ) {
425  blood_covered = true;
426  }
427 
428  if( one_in( 8 ) ) {
429  blood_inside = true;
430  }
431 
432  for( const vpart_reference &vp : get_parts_including_carried( "FRIDGE" ) ) {
433  vp.part().enabled = true;
434  }
435 
436  for( const vpart_reference &vp : get_parts_including_carried( "FREEZER" ) ) {
437  vp.part().enabled = true;
438  }
439 
440  for( const vpart_reference &vp : get_parts_including_carried( "WATER_PURIFIER" ) ) {
441  vp.part().enabled = true;
442  }
443  }
444 
445  std::optional<point> blood_inside_pos;
446  for( const vpart_reference &vp : get_all_parts() ) {
447  const size_t p = vp.part_index();
448  vehicle_part &pt = vp.part();
449 
450  if( vp.has_feature( VPFLAG_REACTOR ) ) {
451  // De-hardcoded reactors. Should always start active
452  pt.enabled = true;
453  }
454 
455  if( pt.is_reactor() ) {
456  rng_fuel_amount( pt, itype_plut_cell );
457  } else if( pt.is_battery() ) {
458  rng_fuel_amount( pt, itype_battery );
459  } else if( pt.is_tank() || pt.is_fuel_store() ) {
460  rng_fuel_amount( pt, pt.ammo_current() );
461  }
462 
463  if( vp.has_feature( "OPENABLE" ) ) { // doors are closed
464  if( !pt.open && one_in( 4 ) ) {
465  open( p );
466  }
467  }
468  if( vp.has_feature( "BOARDABLE" ) ) { // no passengers
470  }
471 
472  // initial vehicle damage
473  if( veh_status == 0 ) {
474  // Completely mint condition vehicle
475  set_hp( pt, vp.info().durability, false );
476  } else {
477  //a bit of initial damage :)
478  //clamp 4d8 to the range of [8,20]. 8=broken, 20=undamaged.
479  int broken = 8;
480  int unhurt = 20;
481  int roll = dice( 4, 8 );
482  if( roll < unhurt ) {
483  if( roll <= broken ) {
484  set_hp( pt, 0, false );
485  pt.ammo_unset(); //empty broken batteries and fuel tanks
486  } else {
487  set_hp( pt, ( roll - broken ) / static_cast<double>( unhurt - broken ) * vp.info().durability,
488  false );
489  }
490  } else {
491  set_hp( pt, vp.info().durability, false );
492  }
493 
494  if( vp.has_feature( VPFLAG_ENGINE ) ) {
495  // If possible set an engine fault rather than destroying the engine outright
496  if( destroyEngine && pt.faults_potential().empty() ) {
497  set_hp( pt, 0, false );
498  } else if( destroyEngine ) {
499  do {
501  } while( one_in( 3 ) );
502  }
503 
504  } else if( ( destroySeats && ( vp.has_feature( "SEAT" ) || vp.has_feature( "SEATBELT" ) ) ) ||
505  ( destroyControls && ( vp.has_feature( "CONTROLS" ) || vp.has_feature( "SECURITY" ) ) ) ||
506  ( destroyAlarm && vp.has_feature( "SECURITY" ) ) ) {
507  set_hp( pt, 0, false );
508  }
509 
510  // Fuel tanks should be emptied as well
511  if( destroyTank && pt.is_fuel_store() ) {
512  set_hp( pt, 0, false );
513  pt.ammo_unset();
514  }
515 
516  //Solar panels have 25% of being destroyed
517  if( vp.has_feature( "SOLAR_PANEL" ) && one_in( 4 ) && init_veh_status != 2 ) {
518  set_hp( pt, 0, false );
519  }
520 
521  /* Bloodsplatter the front-end parts. Assume anything with x > 0 is
522  * the "front" of the vehicle (since the driver's seat is at (0, 0).
523  * We'll be generous with the blood, since some may disappear before
524  * the player gets a chance to see the vehicle. */
525  if( blood_covered && vp.mount().x > 0 ) {
526  if( one_in( 3 ) ) {
527  //Loads of blood. (200 = completely red vehicle part)
528  pt.blood = rng( 200, 600 );
529  } else {
530  //Some blood
531  pt.blood = rng( 50, 200 );
532  }
533  }
534 
535  if( blood_inside ) {
536  // blood is splattered around (blood_inside_pos),
537  // coordinates relative to mount point; the center is always a seat
538  if( blood_inside_pos ) {
539  const int distSq = std::pow( blood_inside_pos->x - vp.mount().x, 2 ) +
540  std::pow( blood_inside_pos->y - vp.mount().y, 2 );
541  if( distSq <= 1 ) {
542  pt.blood = rng( 200, 400 ) - distSq * 100;
543  }
544  } else if( vp.has_feature( "SEAT" ) ) {
545  // Set the center of the bloody mess inside
546  blood_inside_pos.emplace( vp.mount() );
547  }
548  }
549  }
550  //sets the vehicle to locked, if there is no key and an alarm part exists
551  if( vp.has_feature( "SECURITY" ) && has_no_key && pt.is_available() ) {
552  is_locked = true;
553 
554  if( one_in( 2 ) ) {
555  // if vehicle has immobilizer 50% chance to add additional fault
557  }
558  }
559  }
560  // destroy tires until the vehicle is not drivable
561  if( destroyTires && !wheelcache.empty() ) {
562  int tries = 0;
563  while( valid_wheel_config() && tries < 100 ) {
564  // wheel config is still valid, destroy the tire.
565  set_hp( parts[random_entry( wheelcache )], 0, false );
566  tries++;
567  }
568  }
569 
570  // Additional 50% chance for heavy damage to disabled vehicles
571  if( veh_status == 1 && one_in( 2 ) ) {
572  smash( placed_on, 0.5 );
573  }
574 
575  for( const int p : engines ) {
576  auto_select_fuel( parts[p] );
577  }
578 
579  refresh();
580 }
bool valid_wheel_config() const
Definition: vehicle.cpp:4764
bool auto_select_fuel(vehicle_part &vp)
vehicle_part_with_feature_range< std::string > get_parts_including_carried(std::string feature) const
Yields a range of parts of this vehicle that each have the given feature and are not broken or remove...
Definition: vehicle.cpp:3023
void smash(map &m, float hp_percent_loss_min=0.1f, float hp_percent_loss_max=1.2f, float percent_of_parts_to_affect=1.0f, point damage_origin=point_zero, float damage_size=0)
Smashes up a vehicle that has already been placed; used for generating very damaged vehicles.
Definition: vehicle.cpp:863
void set_hp(vehicle_part &pt, int qty, bool keep_degradation, int new_degradation=-1)
Set stat for part constrained by range [0,durability].
@ broken
Definition: enums.h:417
double rand(std::vector< double > const &params)
constexpr time_point turn_zero
Represents time point 0.
Definition: calendar.h:541
double normal_roll(double mean, double stddev)
Definition: rng.cpp:78
int dice(int number, int sides)
Definition: rng.cpp:123
bool is_reactor() const
Is this part a reactor?
std::set< fault_id > faults_potential() const
Faults which could potentially occur with this part (if any)
bool fault_set(const fault_id &f)
Try to set fault returning false if specified fault cannot occur with this item.
void remove_flag(const vp_flag flag) noexcept
Definition: vehicle.h:283
bool is_battery() const
Can this part store electrical charge?
@ VPFLAG_CONE_LIGHT
Definition: veh_type.h:63
@ VPFLAG_REACTOR
Definition: veh_type.h:107
@ VPFLAG_CIRCLE_LIGHT
Definition: veh_type.h:66
@ VPFLAG_AISLE_LIGHT
Definition: veh_type.h:85
@ VPFLAG_ATOMIC_LIGHT
Definition: veh_type.h:86
@ VPFLAG_WIDE_CONE_LIGHT
Definition: veh_type.h:64
@ VPFLAG_HALF_CIRCLE_LIGHT
Definition: veh_type.h:65
@ VPFLAG_DOME_LIGHT
Definition: veh_type.h:84
static const fault_id fault_engine_immobiliser("fault_engine_immobiliser")
static const itype_id itype_battery("battery")
static const itype_id itype_plut_cell("plut_cell")

References vehicle_part::ammo_current(), vehicle_part::ammo_unset(), auto_select_fuel(), vehicle_part::blood, broken, clamp(), dice(), vpart_info::durability, vehicle_part::enabled, engine_on, engines, fault_engine_immobiliser, vehicle_part::fault_set(), vehicle_part::faults_potential(), fuel_type_muscle, get_all_parts(), get_parts_including_carried(), has_engine_type_not(), vpart_info::has_flag(), has_owner(), vehicle_part::info(), vehicle_part::is_available(), vehicle_part::is_battery(), vehicle_part::is_fuel_store(), is_locked, vehicle_part::is_reactor(), vehicle_part::is_tank(), itype_battery, itype_plut_cell, last_update, max(), normal_roll(), one_in(), vehicle_part::open, open(), parts, passenger_flag, rand(), random_entry(), refresh(), vehicle_part::remove_flag(), rng(), set_hp(), smash(), calendar::turn, calendar::turn_zero, valid_wheel_config(), VPFLAG_AISLE_LIGHT, VPFLAG_ATOMIC_LIGHT, VPFLAG_CIRCLE_LIGHT, VPFLAG_CONE_LIGHT, VPFLAG_DOME_LIGHT, VPFLAG_ENGINE, VPFLAG_HALF_CIRCLE_LIGHT, VPFLAG_REACTOR, VPFLAG_WIDE_CONE_LIGHT, and wheelcache.

◆ install_part() [1/4]

int vehicle::install_part ( const point dp,
const vpart_id type 
)

◆ install_part() [2/4]

int vehicle::install_part ( const point dp,
const vpart_id type,
item &&  base 
)

Definition at line 1455 of file vehicle.cpp.

1456 {
1457  return install_part( dp, vehicle_part( type, std::move( base ) ) );
1458 }

References install_part(), and type.

◆ install_part() [3/4]

int vehicle::install_part ( const point dp,
const vpart_id type,
item &&  base,
std::vector< item > &  installed_with 
)

Definition at line 1460 of file vehicle.cpp.

1462 {
1463  return install_part( dp, vehicle_part( type, std::move( base ), installed_with ) );
1464 }

References install_part(), and type.

◆ install_part() [4/4]

int vehicle::install_part ( const point dp,
vehicle_part &&  vp 
)

Definition at line 1466 of file vehicle.cpp.

1467 {
1468  const vpart_info &vpi = vp.info();
1469  const ret_val<void> valid_mount = can_mount( dp, vpi );
1470  if( !valid_mount.success() ) {
1471  debugmsg( "installing %s would make invalid vehicle: %s", vpi.id.str(), valid_mount.str() );
1472  return -1;
1473  }
1474  // Should be checked before installing the part
1475  bool enable = false;
1476  if( vp.is_engine() ) {
1477  enable = true;
1478  // if smart controller is enabled there is charge in battery, no need to test it
1481  engine_on = true;
1483  }
1484  } else {
1485  // TODO: read toggle groups from JSON
1486  static const std::vector<std::string> enable_like = {{
1487  "CONE_LIGHT",
1488  "CIRCLE_LIGHT",
1489  "AISLE_LIGHT",
1490  "AUTOPILOT",
1491  "DOME_LIGHT",
1492  "ATOMIC_LIGHT",
1493  "STEREO",
1494  "CHIMES",
1495  "FRIDGE",
1496  "FREEZER",
1497  "RECHARGE",
1498  "PLOW",
1499  "REAPER",
1500  "PLANTER",
1501  "SCOOP",
1502  "SPACE_HEATER",
1503  "COOLER",
1504  "WATER_PURIFIER",
1505  "ROCKWHEEL",
1506  "ROADHEAD"
1507  }
1508  };
1509 
1510  for( const std::string &flag : enable_like ) {
1511  if( vpi.has_flag( flag ) ) {
1512  enable = has_part( flag, true );
1513  break;
1514  }
1515  }
1516  }
1517  // refresh will add them back if needed
1518  remove_fake_parts( true );
1519  vehicle_part &vp_installed = parts.emplace_back( std::move( vp ) );
1520  vp_installed.enabled = enable;
1521  vp_installed.mount = dp;
1522  const int vp_installed_index = parts.size() - 1;
1523  refresh();
1524  coeff_air_changed = true;
1525  return vp_installed_index;
1526 }
bool success() const
Definition: ret_val.h:13
const std::string & str() const
Definition: ret_val.h:17
ret_val< void > can_mount(const point &dp, const vpart_info &vpi) const
Definition: vehicle.cpp:1181
void remove_fake_parts(bool cleanup=true)
Definition: vehicle.cpp:6516
void do_vehicle_engine_sfx()
Definition: sounds.cpp:2014

References can_mount(), coeff_air_changed, debugmsg, sfx::do_vehicle_engine_sfx(), vehicle_part::enabled, engine_on, vpart_info::fuel_type, fuel_type_battery, has_available_electric_engine(), has_enabled_smart_controller, vpart_info::has_flag(), has_part(), vpart_info::id, vehicle_part::mount, parts, refresh(), remove_fake_parts(), ret_val_common::str(), string_id< T >::str(), and ret_val_common::success().

◆ interact_with()

void vehicle::interact_with ( const tripoint p,
bool  with_pickup = false 
)

Definition at line 2434 of file vehicle_use.cpp.

2435 {
2436  const optional_vpart_position ovp = get_map().veh_at( p );
2437  if( !ovp ) {
2438  debugmsg( "interact_with called at %s and no vehicle is found", p.to_string() );
2439  return;
2440  }
2441 
2442  veh_menu menu( *this, _( "Select an action" ) );
2443  do {
2444  menu.reset();
2445  build_interact_menu( menu, p, with_pickup );
2446  } while( menu.query() );
2447 }
void build_interact_menu(veh_menu &menu, const tripoint &p, bool with_pickup)

References _, build_interact_menu(), debugmsg, get_map(), veh_menu::query(), veh_menu::reset(), tripoint::to_string(), and map::veh_at().

Referenced by game::control_vehicle(), and iuse::remoteveh().

◆ invalidate_mass()

void vehicle::invalidate_mass ( )

◆ invalidate_towing()

void vehicle::invalidate_towing ( bool  first_vehicle = false,
Character remover = nullptr 
)

Definition at line 6828 of file vehicle.cpp.

6829 {
6830  if( !is_towing() && !is_towed() ) {
6831  return;
6832  }
6833  const int tow_cable_idx = get_tow_part();
6834  if( first_vehicle ) {
6835  const bool first_veh_is_towing = is_towing();
6836  vehicle *other_veh = first_veh_is_towing ? tow_data.get_towed() :
6837  is_towed() ? tow_data.get_towed_by() : nullptr;
6838  const int other_tow_cable_idx = other_veh ? other_veh->get_tow_part() : -1;
6839  const point other_tow_cable_mount = other_veh && other_tow_cable_idx > -1 ?
6840  other_veh->part( other_tow_cable_idx ).mount : point();
6841  if( other_veh ) {
6842  other_veh->invalidate_towing();
6843  }
6844  if( tow_cable_idx > -1 ) {
6845  vehicle_part &vp = parts[tow_cable_idx];
6846  item drop = part_to_item( vp );
6847  drop.set_damage( 0 );
6848  tripoint drop_pos = global_part_pos3( vp );
6849  remove_part( vp );
6850  if( other_tow_cable_idx > -1 ) {
6851  drop.reset_link( false );
6852  drop.link_to( *other_veh, other_tow_cable_mount, link_state::vehicle_tow );
6853  if( first_veh_is_towing ) {
6854  drop.link().source = link_state::no_link;
6856  } else {
6858  drop.link().target = link_state::no_link;
6859  }
6860  } else {
6861  drop.reset_link();
6862  }
6863 
6864  if( remover != nullptr ) {
6865  if( !drop.has_flag( flag_NO_DROP ) && remover->can_stash( drop ) ) {
6866  remover->i_add_or_drop( drop );
6867  } else {
6868  std::list<item> drops{ drop };
6870  }
6871  } else {
6872  get_map().add_item_or_charges( drop_pos, drop );
6873  }
6874  }
6876  } else {
6877  if( tow_cable_idx > -1 ) {
6878  vehicle_part &vp = parts[tow_cable_idx];
6879  remove_part( vp );
6880  }
6882  }
6883 }
void put_into_vehicle_or_drop(Character &you, item_drop_reason, const std::list< item > &items)
bool can_stash(const item &it, bool ignore_pkt_settings=false)
Definition: character.cpp:1494
bool i_add_or_drop(item &it, int qty=1, const item *avoid=nullptr, const item *original_inventory_item=nullptr)
Sets invlet and adds to inventory if possible, drops otherwise, returns true if either succeeded.
bool reset_link(bool unspool_if_too_long=true, Character *p=nullptr, int vpart_index=-1, bool loose_message=false, tripoint cable_position=tripoint_zero)
Resets a cable item back to its initial state.
Definition: item.cpp:13816
item::link_data & link()
Gets the item's link data, initializing it if needed.
Definition: item.cpp:13290
ret_val< void > link_to(const optional_vpart_position &linked_vp, link_state link_type=link_state::no_link)
Initializes the item's link_data and starts a connection to the specified vehicle position.
Definition: item.cpp:13348
void clear_towing()
Definition: vehicle.h:208
vehicle * get_towed_by() const
Definition: vehicle.h:201
bool is_towed() const
Definition: vehicle.cpp:6767
const flag_id flag_NO_DROP("NO_DROP")

References map::add_item_or_charges(), Character::can_stash(), towing_data::clear_towing(), deliberate, flag_NO_DROP, get_map(), get_tow_part(), towing_data::get_towed(), towing_data::get_towed_by(), global_part_pos3(), item::has_flag(), Character::i_add_or_drop(), invalidate_towing(), is_towed(), is_towing(), item::link(), item::link_to(), vehicle_part::mount, no_link, part(), part_to_item(), parts, point, put_into_vehicle_or_drop(), remove_part(), item::reset_link(), item::set_damage(), item::link_data::source, item::link_data::target, tow_data, and vehicle_tow.

Referenced by break_off(), veh_interact::complete_vehicle(), damage_direct(), map::detach_vehicle(), do_towing_move(), invalidate_towing(), merge_rackable_vehicle(), map::move_vehicle(), and unlink_cables().

◆ is_alternator_on()

bool vehicle::is_alternator_on ( const vehicle_part vp) const

Definition at line 1020 of file vehicle.cpp.

1021 {
1022  if( vp.is_unavailable() ) {
1023  return false;
1024  }
1025  for( const int p : engines ) {
1026  const vehicle_part &vp_engine = parts[p];
1027  if( vp_engine.mount == vp.mount
1028  && vp_engine.is_available()
1029  && vp_engine.enabled
1030  && fuel_left( vp_engine.fuel_current() )
1031  && !vp_engine.has_fault_flag( "NO_ALTERNATOR_CHARGE" ) ) {
1032  return true; // the engine can drive its alternator
1033  }
1034  }
1035  return false;
1036 }

References vehicle_part::enabled, engines, vehicle_part::fuel_current(), fuel_left(), vehicle_part::has_fault_flag(), vehicle_part::is_available(), vehicle_part::is_unavailable(), vehicle_part::mount, and parts.

Referenced by total_alternator_epower(), total_power(), and update_alternator_load().

◆ is_appliance()

bool vehicle::is_appliance ( ) const
Returns
true if vehicle is an appliance

Definition at line 1445 of file vehicle.cpp.

1446 {
1447  return has_tag( flag_APPLIANCE );
1448 }
bool has_tag(const std::string &tag) const
Definition: vehicle.cpp:8322

References flag_APPLIANCE(), and has_tag().

Referenced by build_interact_menu(), can_do_activity_there(), is_foldable(), refresh(), and split_vehicles().

◆ is_connected()

bool vehicle::is_connected ( const vehicle_part to,
const vehicle_part from,
const vehicle_part excluded_part 
) const
private

Performs a breadth-first search from one part to another, to see if a path exists between the two without going through the excluded part.

Used to see if a part can be legally removed.

Parameters
toThe part to reach.
fromThe part to start the search from.
excluded_partThe part that is being removed and, therefore, should not be included in the path.
Returns
true if a path exists without the excluded part, false otherwise.

Definition at line 1395 of file vehicle.cpp.

1397 {
1398  const point target = to.mount;
1399  const point excluded = excluded_part.mount;
1400 
1401  std::queue<point> queue;
1402  std::unordered_set<point> visited;
1403 
1404  queue.push( from.mount );
1405  visited.insert( from.mount );
1406  while( !queue.empty() ) {
1407  const point current_pt = queue.front();
1408  queue.pop();
1409 
1410  // in this case BFS "edges" are north/east/west/south tiles, diagonals don't connect
1411  for( const point &offset : four_adjacent_offsets ) {
1412  const point next = current_pt + offset;
1413 
1414  if( next == target ) {
1415  return true; // found a path, bail out early from BFS
1416  }
1417 
1418  if( next == excluded ) {
1419  continue; // can't traverse excluded tile
1420  }
1421 
1422  const std::vector<int> parts_there = parts_at_relative( next, false );
1423 
1424  if( parts_there.empty() ) {
1425  continue; // can't traverse empty tiles
1426  }
1427 
1428  // 2022-08-27 assuming structure part is on 0th index is questionable but it worked before so...
1429  vehicle_part vp_next = parts[ parts_there[ 0 ] ];
1430 
1431  if( vp_next.info().location != part_location_structure || // not a structure part
1432  vp_next.info().has_flag( "PROTRUSION" ) || // protrusions are not really a structure
1433  vp_next.has_flag( vp_flag::carried_flag ) ) { // carried frames are not a structure
1434  continue; // can't connect if it's not a structure
1435  }
1436 
1437  if( visited.insert( vp_next.mount ).second ) { // .second is false if already in visited
1438  queue.push( vp_next.mount ); // not visited, need to explore
1439  }
1440  }
1441  }
1442  return false;
1443 }

References carried_flag, four_adjacent_offsets, vpart_info::has_flag(), vehicle_part::has_flag(), vehicle_part::info(), vpart_info::location, vehicle_part::mount, part_location_structure(), parts, and parts_at_relative().

Referenced by can_unmount().

◆ is_engine_on()

bool vehicle::is_engine_on ( const vehicle_part vp) const

◆ is_engine_type()

bool vehicle::is_engine_type ( const vehicle_part vp,
const itype_id ft 
) const

◆ is_engine_type_combustion()

bool vehicle::is_engine_type_combustion ( const vehicle_part vp) const

Definition at line 1005 of file vehicle.cpp.

1006 {
1007  return vp.info().has_flag( flag_E_COMBUSTION );
1008 }
static const std::string flag_E_COMBUSTION("E_COMBUSTION")

References flag_E_COMBUSTION(), vpart_info::has_flag(), and vehicle_part::info().

Referenced by noise_and_smoke(), and smart_controller_handle_turn().

◆ is_engine_type_on()

bool vehicle::is_engine_type_on ( const vehicle_part vp,
const itype_id ft 
) const

Definition at line 952 of file vehicle.cpp.

953 {
954  return is_engine_on( vp ) && is_engine_type( vp, ft );
955 }

References is_engine_on(), and is_engine_type().

Referenced by basic_consumption().

◆ is_external_part()

bool vehicle::is_external_part ( const tripoint part_pt) const

Definition at line 6737 of file vehicle.cpp.

6738 {
6739  map &here = get_map();
6740  for( const tripoint &elem : here.points_in_radius( part_pt, 1 ) ) {
6741  const optional_vpart_position vp = here.veh_at( elem );
6742  if( !vp ) {
6743  return true;
6744  }
6745  if( &vp->vehicle() != this ) {
6746  return true;
6747  }
6748  }
6749  return false;
6750 }

References get_map(), map::points_in_radius(), and map::veh_at().

Referenced by item::link_to().

◆ is_flyable()

bool vehicle::is_flyable ( ) const

Definition at line 4397 of file vehicle.cpp.

4398 {
4399  return flyable;
4400 }

References flyable.

Referenced by damage_direct(), and pldrive().

◆ is_flying_in_air()

bool vehicle::is_flying_in_air ( ) const

◆ is_foldable()

bool vehicle::is_foldable ( ) const

Definition at line 7594 of file vehicle.cpp.

7595 {
7596  if( is_appliance() ) {
7597  return false;
7598  }
7599  for( const vehicle_part &vp : real_parts() ) {
7600  if( !vp.info().folded_volume ) {
7601  return false;
7602  }
7603  }
7604  return true;
7605 }

References is_appliance(), and real_parts().

Referenced by veh_interact::do_install(), and vehicle_folding_activity_actor::fold_vehicle().

◆ is_in_water()

bool vehicle::is_in_water ( bool  deep_water = false) const

is the vehicle mostly in water or mostly on fairly dry land?

Definition at line 4462 of file vehicle.cpp.

4463 {
4464  return deep_water ? in_deep_water : in_water;
4465 }

References in_deep_water, and in_water.

Referenced by on_move(), map::vehicle_wheel_traction(), and wait().

◆ is_moving()

bool vehicle::is_moving ( ) const

Definition at line 3728 of file vehicle.cpp.

3729 {
3730  return velocity != 0;
3731 }

References velocity.

Referenced by build_interact_menu(), gain_moves(), map::get_moving_vehicle_targets(), monster::move(), Character::pause(), thrust(), and npc::vehicle_danger().

◆ is_old_owner()

bool vehicle::is_old_owner ( const Character c,
bool  available_to_take = false 
) const

Definition at line 4656 of file vehicle.cpp.

4657 {
4658  if( old_owner.is_null() ) {
4659  return available_to_take;
4660  }
4661  if( !c.get_faction() ) {
4662  debugmsg( "vehicle::is_old_owner() player %s has no faction", c.disp_name() );
4663  return false;
4664  }
4665  return c.get_faction()->id == get_old_owner();
4666 }
faction_id get_old_owner() const
Definition: vehicle.h:980
static constexpr double c
Definition: magic.cpp:1568

References c, debugmsg, get_old_owner(), string_id< T >::is_null(), and old_owner.

◆ is_owned_by()

bool vehicle::is_owned_by ( const Character c,
bool  available_to_take = false 
) const

Definition at line 4644 of file vehicle.cpp.

4645 {
4646  if( owner.is_null() ) {
4647  return available_to_take;
4648  }
4649  if( !c.get_faction() ) {
4650  debugmsg( "vehicle::is_owned_by() player %s has no faction", c.disp_name() );
4651  return false;
4652  }
4653  return c.get_faction()->id == get_owner();
4654 }

References c, debugmsg, get_owner(), string_id< T >::is_null(), and owner.

Referenced by assign_veh_to_follow(), game::chat(), veh_interact::display_name(), handle_potential_theft(), tell_magic_veh_to_follow(), and tell_veh_stop_following().

◆ is_passenger()

bool vehicle::is_passenger ( Character c) const

Definition at line 3389 of file vehicle.cpp.

3390 {
3391  if( !c.in_vehicle ) {
3392  return false;
3393  }
3394  std::vector<int> psg_parts = boarded_parts();
3395  for( const int &psg_part : psg_parts ) {
3396  if( get_passenger( psg_part ) == &c ) {
3397  return true;
3398  }
3399  }
3400  return false;
3401 }

References boarded_parts(), c, and get_passenger().

Referenced by on_move(), and part_displayed_at().

◆ is_perpetual_type()

bool vehicle::is_perpetual_type ( const vehicle_part vp) const

◆ is_powergrid()

bool vehicle::is_powergrid ( ) const

Definition at line 1952 of file vehicle.cpp.

1953 {
1954  if( !has_tag( flag_APPLIANCE ) ) {
1955  return false;
1956  }
1957 
1958  return !solar_panels.empty() || !reactors.empty() || !wind_turbines.empty() ||
1959  !water_wheels.empty() || !alternators.empty() || !batteries.empty() || has_tag( flag_WIRING );
1960 }
std::vector< int > solar_panels
Definition: vehicle.h:2175
std::vector< int > wind_turbines
Definition: vehicle.h:2176
std::vector< int > water_wheels
Definition: vehicle.h:2177
std::vector< int > alternators
Definition: vehicle.h:2172
static const std::string flag_WIRING("WIRING")

References alternators, batteries, flag_APPLIANCE(), flag_WIRING(), has_tag(), reactors, solar_panels, water_wheels, and wind_turbines.

Referenced by link_up_actor::link_to_veh_app(), part_removal_cleanup(), place_appliance(), veh_app_interact::populate_app_actions(), and split_vehicles().

◆ is_rotorcraft()

bool vehicle::is_rotorcraft ( ) const

◆ is_structural_part_removed()

bool vehicle::is_structural_part_removed ( ) const
private

Returns whether or not the vehicle has a structural part queued for removal,.

Returns
true if a structural is queue for removal, false if not.

Definition at line 1171 of file vehicle.cpp.

1172 {
1173  for( const vpart_reference &vp : get_all_parts() ) {
1174  if( vp.part().removed && vp.info().location == part_location_structure ) {
1175  return true;
1176  }
1177  }
1178  return false;
1179 }

References get_all_parts(), and part_location_structure().

Referenced by can_mount().

◆ is_towed()

bool vehicle::is_towed ( ) const

Definition at line 6767 of file vehicle.cpp.

6768 {
6769  bool ret = false;
6770  if( !tow_data.get_towed_by() ) {
6771  return ret;
6772  } else {
6773  if( !tow_data.get_towed_by()->tow_data.get_towed() ) {
6774  debugmsg( "vehicle %s is marked as towed, but the tower vehicle has no towed defined", name );
6775  return ret;
6776  }
6777  ret = true;
6778  }
6779  return ret;
6780 }

References debugmsg, towing_data::get_towed(), towing_data::get_towed_by(), name, cata::hash64_detail::ret, and tow_data.

Referenced by invalidate_towing(), item::link_to(), selfdrive(), split_vehicles(), and static_drag().

◆ is_towing()

bool vehicle::is_towing ( ) const

Definition at line 6752 of file vehicle.cpp.

6753 {
6754  bool ret = false;
6755  if( !tow_data.get_towed() ) {
6756  return ret;
6757  } else {
6758  if( !tow_data.get_towed()->tow_data.get_towed_by() ) {
6759  debugmsg( "vehicle %s is towing, but the towed vehicle has no tower defined", name );
6760  return ret;
6761  }
6762  ret = true;
6763  }
6764  return ret;
6765 }

References debugmsg, towing_data::get_towed(), towing_data::get_towed_by(), name, cata::hash64_detail::ret, and tow_data.

Referenced by ground_acceleration(), invalidate_towing(), item::link_to(), map::move_vehicle(), slowdown(), split_vehicles(), thrust(), and water_acceleration().

◆ is_watercraft()

bool vehicle::is_watercraft ( ) const

should vehicle be handled using watercraft logic as determined by amount of water it is in (and whether it is amphibious) result being true does not guarantee it is viable boat – check can_float()

Definition at line 4457 of file vehicle.cpp.

4458 {
4459  return in_deep_water || ( in_water && wheelcache.empty() );
4460 }

References in_deep_water, in_water, and wheelcache.

Referenced by acceleration(), act_on_map(), k_traction(), max_velocity(), map::move_vehicle(), on_move(), safe_velocity(), slowdown(), steering_effectiveness(), thrust(), map::vehicle_wheel_traction(), and wait().

◆ is_wheel_state_correct_to_turn_on_rails()

bool vehicle::is_wheel_state_correct_to_turn_on_rails ( int  wheels_on_rail,
int  wheel_count,
int  turning_wheels_that_are_one_axis 
) const

Definition at line 1800 of file vehicle_move.cpp.

1802 {
1803  return ( wheels_on_rail >= 2 || // minimum wheels to be able to turn (excluding one axis vehicles)
1804  ( wheels_on_rail == 1 && ( wheel_count == 1 ||
1805  all_wheels_on_one_axis ) ) ) // for bikes or 1 wheel vehicle
1806  && ( wheels_on_rail !=
1807  turning_wheels_that_are_one_axis // wheels that want to turn is not on same axis
1810  // allow turn for vehicles with wheel distance < 4 when moving backwards
1811 }
bool all_wheels_on_one_axis
Definition: vehicle.h:2350
bounding_box rail_wheel_bounding_box
Definition: vehicle.h:2305
point p1
Definition: vehicle.h:218
point p2
Definition: vehicle.h:219

References abs(), all_wheels_on_one_axis, bounding_box::p1, bounding_box::p2, rail_wheel_bounding_box, velocity, and point::x.

Referenced by allow_auto_turn_on_rails(), and allow_manual_turn_on_rails().

◆ k_traction()

float vehicle::k_traction ( float  wheel_traction_area) const

Traction coefficient of the vehicle.

1.0 on road. Outside roads, depends on mass divided by wheel area and the surface beneath wheels.

Affects safe velocity, acceleration and handling difficulty.

Definition at line 4560 of file vehicle.cpp.

4561 {
4562  if( in_deep_water ) {
4563  return can_float() ? 1.0f : -1.0f;
4564  }
4565  if( is_flying ) {
4566  return is_rotorcraft() ? 1.0f : -1.0f;
4567  }
4568  if( is_watercraft() && can_float() ) {
4569  return 1.0f;
4570  }
4571 
4572  const float fraction_without_traction = 1.0f - wheel_traction_area / wheel_area();
4573  if( fraction_without_traction == 0 ) {
4574  return 1.0f;
4575  }
4576  const float mass_penalty = fraction_without_traction * to_kilogram( total_mass() );
4577  float traction = std::min( 1.0f, wheel_traction_area / mass_penalty );
4578  add_msg_debug( debugmode::DF_VEHICLE, "%s has traction %.2f", name, traction );
4579 
4580  // For now make it easy until it gets properly balanced: add a low cap of 0.1
4581  return std::max( 0.1f, traction );
4582 }
int wheel_area() const
Calculates the sum of the area under the wheels of the vehicle.
Definition: vehicle.cpp:4105

References add_msg_debug, can_float(), debugmode::DF_VEHICLE, in_deep_water, is_flying, is_rotorcraft(), is_watercraft(), max(), min(), name, units::to_kilogram(), total_mass(), and wheel_area().

Referenced by act_on_map(), veh_interact::display_stats(), overmap_ui::get_overmap_path_to(), game::grabbed_veh_move(), handling_difficulty(), smart_controller_handle_turn(), and thrust().

◆ leak_fuel()

void vehicle::leak_fuel ( vehicle_part pt) const
private

empty the contents of a tank, battery or turret spilling liquids randomly on the ground

Definition at line 7545 of file vehicle.cpp.

7546 {
7547  // only liquid fuels from non-empty tanks can leak out onto map tiles
7548  if( !pt.is_tank() || pt.ammo_remaining() <= 0 ) {
7549  return;
7550  }
7551 
7552  map &here = get_map();
7553  // leak in random directions but prefer closest tiles and avoid walls or other obstacles
7554  std::vector<tripoint> tiles = closest_points_first( global_part_pos3( pt ), 1 );
7555  tiles.erase( std::remove_if( tiles.begin(), tiles.end(), [&here]( const tripoint & e ) {
7556  return !here.passable( e );
7557  } ), tiles.end() );
7558 
7559  // leak up to 1/3 of remaining fuel per iteration and continue until the part is empty
7560  const itype *fuel = item::find_type( pt.ammo_current() );
7561  while( !tiles.empty() && pt.ammo_remaining() ) {
7562  int qty = pt.ammo_consume( rng( 0, std::max( pt.ammo_remaining() / 3, 1 ) ),
7563  global_part_pos3( pt ) );
7564  if( qty > 0 ) {
7565  here.add_item_or_charges( random_entry( tiles ), item( fuel, calendar::turn, qty ) );
7566  }
7567  }
7568 
7569  pt.ammo_unset();
7570 }
static const itype * find_type(const itype_id &type)
Returns the item type of the given identifier.
Definition: item.cpp:14581
std::vector< coords::coord_point< Point, Origin, Scale > > closest_points_first(const coords::coord_point< Point, Origin, Scale > &loc, int min_dist, int max_dist)
Definition: coordinates.h:848
Definition: itype.h:1186

References map::add_item_or_charges(), vehicle_part::ammo_consume(), vehicle_part::ammo_current(), vehicle_part::ammo_remaining(), vehicle_part::ammo_unset(), closest_points_first(), item::find_type(), get_map(), global_part_pos3(), vehicle_part::is_tank(), item, max(), random_entry(), rng(), and calendar::turn.

Referenced by damage_direct(), and explode_fuel().

◆ level_vehicle()

bool vehicle::level_vehicle ( )

Definition at line 1988 of file vehicle_move.cpp.

1989 {
1990  map &here = get_map();
1991  if( is_flying && is_rotorcraft() ) {
1992  return true;
1993  }
1994  is_on_ramp = false;
1995  // make sure that all parts are either supported across levels or on the same level
1996  std::map<int, bool> no_support;
1997  for( vehicle_part &prt : parts ) {
1998  if( prt.info().location != part_location_structure ) {
1999  continue;
2000  }
2001  const tripoint part_pos = global_part_pos3( prt );
2002  if( no_support.find( part_pos.z ) == no_support.end() ) {
2003  no_support[part_pos.z] = part_pos.z > -OVERMAP_DEPTH;
2004  }
2005  if( no_support[part_pos.z] ) {
2006  no_support[part_pos.z] = here.has_flag_ter_or_furn( ter_furn_flag::TFLAG_NO_FLOOR, part_pos ) &&
2007  !here.supports_above( part_pos + tripoint_below );
2008  }
2009  if( !is_on_ramp &&
2010  ( here.has_flag( ter_furn_flag::TFLAG_RAMP_UP, tripoint( part_pos.xy(), part_pos.z - 1 ) ) ||
2011  here.has_flag( ter_furn_flag::TFLAG_RAMP_DOWN, tripoint( part_pos.xy(), part_pos.z + 1 ) ) ) ) {
2012  is_on_ramp = true;
2013  }
2014  }
2015  std::set<int> dropped_parts;
2016  // if it's unsupported but on the same level, just let it fall
2017  bool center_drop = false;
2018  bool adjust_level = false;
2019  if( no_support.size() > 1 ) {
2020  for( int zlevel = -OVERMAP_DEPTH; zlevel <= OVERMAP_DEPTH; zlevel++ ) {
2021  if( no_support.find( zlevel ) == no_support.end() || !no_support[zlevel] ) {
2022  continue;
2023  }
2024  center_drop |= global_pos3().z == zlevel;
2025  adjust_level = true;
2026  // drop unsupported parts 1 zlevel
2027  for( size_t prt = 0; prt < parts.size(); prt++ ) {
2028  if( global_part_pos3( prt ).z == zlevel ) {
2029  dropped_parts.insert( static_cast<int>( prt ) );
2030  }
2031  }
2032  }
2033  }
2034  if( adjust_level ) {
2035  here.displace_vehicle( *this, tripoint_below, center_drop, dropped_parts );
2036  return false;
2037  } else {
2038  return true;
2039  }
2040 }
bool displace_vehicle(vehicle &veh, const tripoint &dp, bool adjust_pos=true, const std::set< int > &parts_to_move={})
Definition: map.cpp:1435
constexpr tripoint tripoint_below
Definition: point.h:272

References map::displace_vehicle(), get_map(), global_part_pos3(), global_pos3(), map::has_flag(), map::has_flag_ter_or_furn(), is_flying, is_on_ramp, is_rotorcraft(), OVERMAP_DEPTH, part_location_structure(), parts, map::supports_above(), TFLAG_NO_FLOOR, TFLAG_RAMP_DOWN, TFLAG_RAMP_UP, tripoint_below, tripoint::xy(), and tripoint::z.

Referenced by map::level_vehicle().

◆ lift_strength()

int vehicle::lift_strength ( ) const

Required strength to be able to successfully lift the vehicle unaided by equipment.

Definition at line 946 of file vehicle.cpp.

947 {
949  return std::max<std::int64_t>( mass / 10000_gram, 1 );
950 }
units::quantity< int, units::mass_in_microgram_tag > mass
Definition: stomach.h:19

References total_mass().

Referenced by veh_interact::calc_lift_requirements().

◆ lift_thrust_of_rotorcraft()

double vehicle::lift_thrust_of_rotorcraft ( bool  fuelled,
bool  safe = false 
) const

is the vehicle flying? is it a rotorcraft?

Definition at line 4366 of file vehicle.cpp.

4367 {
4368  int rotor_area_in_feet = 0;
4369  for( const int rotor : rotors ) {
4370  double rotor_diameter_in_feet = parts[rotor].info().rotor_info->rotor_diameter * 3.28084;
4371  rotor_area_in_feet += ( M_PI / 4 ) * std::pow( rotor_diameter_in_feet, 2 );
4372  }
4373  // take off 15 % due to the imaginary tail rotor power.
4374  double engine_power_in_hp = 0.00134102 * units::to_watt( total_power( fuelled, safe ) );
4375  // lift_thrust in lbthrust
4376  double lift_thrust = ( 8.8658 * std::pow( engine_power_in_hp / rotor_area_in_feet,
4377  -0.3107 ) ) * engine_power_in_hp;
4379  "lift thrust in lbs of %s = %f, rotor area in feet : %d, engine power in hp %f, thrust in newtons : %f",
4380  name, lift_thrust, rotor_area_in_feet, engine_power_in_hp, lift_thrust * 4.45 );
4381  // convert to newtons.
4382  return lift_thrust * 4.45;
4383 }
#define M_PI
Definition: math_defines.h:23
void safe(Character &you, const tripoint &examp)
Attempt to crack safe through audio-feedback manual lock manipulation.
Definition: iexamine.cpp:1776

References add_msg_debug, debugmode::DF_VEHICLE, M_PI, name, parts, rotors, iexamine::safe(), units::to_watt(), and total_power().

Referenced by has_sufficient_rotorlift(), max_rotor_velocity(), rotor_acceleration(), and safe_rotor_velocity().

◆ lights()

std::vector< vehicle_part * > vehicle::lights ( )

Definition at line 4987 of file vehicle.cpp.

4988 {
4989  std::vector<vehicle_part *> res;
4990  for( vehicle_part &e : parts ) {
4991  if( e.enabled && e.is_available() && e.is_light() ) {
4992  res.push_back( &e );
4993  }
4994  }
4995  return res;
4996 }

References parts.

Referenced by map::generate_lightmap(), and veh_lumi().

◆ local_center_of_mass()

const point & vehicle::local_center_of_mass ( ) const

Definition at line 3492 of file vehicle.cpp.

3493 {
3495  calc_mass_center( false );
3496  }
3497 
3498  return mass_center_no_precalc;
3499 }
void calc_mass_center(bool precalc) const
Definition: vehicle.cpp:7997

References calc_mass_center(), mass_center_no_precalc, and mass_center_no_precalc_dirty.

Referenced by balanced_wheel_config(), veh_interact::display_veh(), and refresh_pivot().

◆ lock()

void vehicle::lock ( int  part_index)

Locks a lockable, closed part at the specified index.

If it's a multipart, locks all attached parts as well. Does not affect vehicle is_locked flag.

Parameters
part_indexThe index in the parts list of the part to lock.

Definition at line 1240 of file vehicle_use.cpp.

1241 {
1242  vehicle_part &vp = part( part_index );
1243  if( !vp.info().has_flag( "LOCKABLE_DOOR" ) ) {
1244  debugmsg( "Attempted to lock non-lockable part %d (%s) on a %s!", part_index, vp.name(), name );
1245  } else if( vp.open ) {
1246  debugmsg( "Attempted to lock open part %d (%s) on a %s!", part_index, vp.name(), name );
1247  } else {
1248  lock_or_unlock( part_index, true );
1249  }
1250 }

References debugmsg, vpart_info::has_flag(), vehicle_part::info(), lock_or_unlock(), vehicle_part::name(), name, vehicle_part::open, and part().

Referenced by control_doors(), and doors::lock_door().

◆ lock_or_unlock()

void vehicle::lock_or_unlock ( int  part_index,
bool  locking 
)
private

Locks or unlocks a lockable door part at the specified index based on the @locking value passed.

Part must have the OPENABLE and LOCKABLE_DOOR flags, and be closed. If it's a multipart, locks or unlocks all attached parts as well.

Parameters
part_indexThe index in the parts list of the part to lock or unlock.

Definition at line 1350 of file vehicle_use.cpp.

1351 {
1352  const auto part_lock_or_unlock = [&]( const int parti, const bool locking ) {
1353  vehicle_part &prt = parts.at( parti );
1354  prt.locked = locking;
1355  if( prt.is_fake ) {
1356  parts.at( prt.fake_part_to ).locked = locking;
1357  } else if( prt.has_fake ) {
1358  parts.at( prt.fake_part_at ).locked = locking;
1359  }
1360  };
1361  //find_lines_of_parts() doesn't return the part_index we passed, so we set it on its own
1362  part_lock_or_unlock( part_index, locking );
1363  for( const std::vector<int> &vec : find_lines_of_parts( part_index, "LOCKABLE_DOOR" ) ) {
1364  for( const int &partID : vec ) {
1365  part_lock_or_unlock( partID, locking );
1366  }
1367  }
1368 }
int fake_part_at
Definition: vehicle.h:576
bool has_fake
Definition: vehicle.h:575

References vehicle_part::fake_part_at, vehicle_part::fake_part_to, find_lines_of_parts(), vehicle_part::has_fake, vehicle_part::is_fake, vehicle_part::locked, and parts.

Referenced by control_doors(), lock(), and unlock().

◆ make_active()

void vehicle::make_active ( item_location loc)

Update an item's active status, for example when adding hot or perishable liquid to a container.

Definition at line 5825 of file vehicle.cpp.

5826 {
5827  item &target = *loc;
5828  auto cargo_parts = get_parts_at( loc.position(), "CARGO", part_status_flag::any );
5829  if( cargo_parts.empty() ) {
5830  return;
5831  }
5832  // System insures that there is only one part in this vector.
5833  vehicle_part *cargo_part = cargo_parts.front();
5834  active_items.add( target, cargo_part->mount );
5835 }

References active_items, active_item_cache::add(), any, get_parts_at(), vehicle_part::mount, and item_location::position().

Referenced by item_location::impl::item_on_vehicle::make_active().

◆ max_ground_velocity()

int vehicle::max_ground_velocity ( bool  fueled = true) const

Definition at line 3879 of file vehicle.cpp.

3880 {
3881  int total_engine_w = units::to_watt( total_power( fueled ) );
3882  double c_rolling_drag = coeff_rolling_drag();
3883  double max_in_mps = simple_cubic_solution( coeff_air_drag(), c_rolling_drag,
3884  c_rolling_drag * vehicles::rolling_constant_to_variable,
3885  -total_engine_w );
3887  "%s: power %d, c_air %3.2f, c_rolling %3.2f, max_in_mps %3.2f",
3888  name, total_engine_w, coeff_air_drag(), c_rolling_drag, max_in_mps );
3889  return mps_to_vmiph( max_in_mps );
3890 }
double coeff_air_drag() const
Physical coefficients used for vehicle calculations.
Definition: vehicle.cpp:4159
double coeff_rolling_drag() const
coefficient of rolling resistance multiplied by velocity to get the variable part of rolling resistan...
Definition: vehicle.cpp:4303
constexpr double rolling_constant_to_variable
Definition: vehicle.h:80
static double simple_cubic_solution(double a, double b, double c, double d)
Definition: vehicle.cpp:3808
int mps_to_vmiph(double mps)

References add_msg_debug, coeff_air_drag(), coeff_rolling_drag(), debugmode::DF_VEHICLE, mps_to_vmiph(), name, vehicles::rolling_constant_to_variable, simple_cubic_solution(), units::to_watt(), and total_power().

Referenced by veh_interact::display_stats(), max_velocity(), and game::place_vehicle_nearby().

◆ max_reactor_epower()

units::power vehicle::max_reactor_epower ( ) const

Definition at line 5195 of file vehicle.cpp.

5196 {
5197  units::power epower = 0_W;
5198  for( const int p : reactors ) {
5199  const vehicle_part &vp = parts[p];
5200  epower += vp.enabled ? part_epower( vp ) : 0_W;
5201  }
5202  return epower;
5203 }

References vehicle_part::enabled, part_epower(), parts, and reactors.

Referenced by veh_interact::calc_overview().

◆ max_reverse_velocity()

int vehicle::max_reverse_velocity ( bool  fueled = true) const

Definition at line 3933 of file vehicle.cpp.

3934 {
3935  int max_vel = max_velocity( fueled );
3936  if( has_engine_type( fuel_type_battery, true ) ) {
3937  // Electric motors can go in reverse as well as forward
3938  return -max_vel;
3939  } else {
3940  // All other motive powers do poorly in reverse
3941  return -max_vel / 4;
3942  }
3943 }
bool has_engine_type(const itype_id &ft, bool enabled) const
Definition: vehicle.cpp:957

References fuel_type_battery, has_engine_type(), and max_velocity().

Referenced by cruise_thrust(), and thrust().

◆ max_rotor_velocity()

int vehicle::max_rotor_velocity ( bool  fueled = true) const

Definition at line 3913 of file vehicle.cpp.

3914 {
3915  const double max_air_mps = std::sqrt( lift_thrust_of_rotorcraft( fueled ) / coeff_air_drag() );
3916  // helicopters just cannot go over 250mph at very maximum
3917  // weird things start happening to their rotors if they do.
3918  // due to the rotor tips going supersonic.
3919  return std::min( 25501, mps_to_vmiph( max_air_mps ) );
3920 }

References coeff_air_drag(), lift_thrust_of_rotorcraft(), min(), mps_to_vmiph(), and sqrt().

Referenced by veh_interact::display_stats(), and max_velocity().

◆ max_velocity()

int vehicle::max_velocity ( bool  fueled = true) const

Definition at line 3922 of file vehicle.cpp.

3923 {
3924  if( is_flying && is_rotorcraft() ) {
3925  return max_rotor_velocity( fueled );
3926  } else if( is_watercraft() ) {
3927  return max_water_velocity( fueled );
3928  } else {
3929  return max_ground_velocity( fueled );
3930  }
3931 }
int max_ground_velocity(bool fueled=true) const
Definition: vehicle.cpp:3879
int max_water_velocity(bool fueled=true) const
Definition: vehicle.cpp:3902
int max_rotor_velocity(bool fueled=true) const
Definition: vehicle.cpp:3913

References is_flying, is_rotorcraft(), is_watercraft(), max_ground_velocity(), max_rotor_velocity(), and max_water_velocity().

Referenced by cruise_thrust(), ground_acceleration(), max_reverse_velocity(), strain(), and thrust().

◆ max_water_velocity()

int vehicle::max_water_velocity ( bool  fueled = true) const

Definition at line 3902 of file vehicle.cpp.

3903 {
3904  int total_engine_w = units::to_watt( total_power( fueled ) );
3905  double total_drag = coeff_water_drag() + coeff_air_drag();
3906  double max_in_mps = std::cbrt( total_engine_w / total_drag );
3908  "%s: power %d, c_air %3.2f, c_water %3.2f, water max_in_mps %3.2f",
3909  name, total_engine_w, coeff_air_drag(), coeff_water_drag(), max_in_mps );
3910  return mps_to_vmiph( max_in_mps );
3911 }

References add_msg_debug, coeff_air_drag(), coeff_water_drag(), debugmode::DF_VEHICLE, mps_to_vmiph(), name, units::to_watt(), and total_power().

Referenced by veh_interact::display_stats(), max_velocity(), and water_acceleration().

◆ merge_appliance_into_grid()

bool vehicle::merge_appliance_into_grid ( vehicle veh_target)

Definition at line 1858 of file vehicle.cpp.

1859 {
1860  if( &veh_target == this ) {
1861  return false;
1862  }
1863  // Release grab if player is dragging either appliance
1864  if( get_avatar().get_grab_type() == object_type::VEHICLE ) {
1865  const tripoint grab_point = get_avatar().pos() + get_avatar().grab_point;
1866  const optional_vpart_position grabbed_veh = get_map().veh_at( grab_point );
1867  if( grabbed_veh && ( &grabbed_veh->vehicle() == this || &grabbed_veh->vehicle() == &veh_target ) ) {
1868  add_msg( _( "You release the %s." ), grabbed_veh->vehicle().name );
1870  }
1871  }
1872  //Reset both grid turn_dir to prevent rotation on merge
1873  turn_dir = 0_degrees;
1874  veh_target.turn_dir = 0_degrees;
1875 
1876  // Ensure both vehicles have the correct position and a part at 0,0. get_bounding_box will update precalcs.
1877  shift_if_needed( get_map() );
1878  pos -= pivot_anchor[0];
1879  veh_target.shift_if_needed( get_map() );
1880  veh_target.pos -= veh_target.pivot_anchor[0];
1881 
1882  bounding_box vehicle_box = get_bounding_box( false, true );
1883  bounding_box target_vehicle_box = veh_target.get_bounding_box( false, true );
1884 
1885  bounding_box combined_box;
1886  combined_box.p1 = point( std::min( vehicle_box.p1.x, target_vehicle_box.p1.x ),
1887  std::min( vehicle_box.p1.y, target_vehicle_box.p1.y ) );
1888  combined_box.p2 = point( std::max( vehicle_box.p2.x, target_vehicle_box.p2.x ),
1889  std::max( vehicle_box.p2.y, target_vehicle_box.p2.y ) );
1890  point size;
1891  size.x = std::abs( ( combined_box.p2 - combined_box.p1 ).x ) + 1;
1892  size.y = std::abs( ( combined_box.p2 - combined_box.p1 ).y ) + 1;
1893 
1894  //Make sure the resulting vehicle would not be too large
1896  if( !merge_vehicle_parts( &veh_target ) ) {
1897  debugmsg( "failed to merge vehicle parts" );
1898  } else {
1899  //Keep wall wiring sections from losing their flag
1900  //A grid with only wires needs this flag to count as a powergrid
1901  //But it's not a problem if a grid without any has this flag, thus we can add it without issue
1902  add_tag( flag_WIRING );
1904  return true;
1905  }
1906  } else {
1907  add_msg( m_bad, _( "Can't merge into %s, the resulting grid would be too big." ), veh_target.name );
1908  }
1909  return false;
1910 }
tripoint grab_point
Definition: character.h:592
void grab(object_type grab_type, const tripoint &grab_point=tripoint_zero)
Definition: avatar.cpp:699
bool merge_vehicle_parts(vehicle *veh)
Definition: vehicle.cpp:1822
void add_tag(const std::string &tag)
Definition: vehicle.cpp:8317
bool shift_if_needed(map &here)
Detect if the vehicle is currently missing a 0,0 part, and adjust if necessary.
Definition: vehicle.cpp:7283
bounding_box get_bounding_box(bool use_precalc=true, bool no_fake=false)
Definition: vehicle.cpp:8056
const size_t size
Definition: omdata.h:66
static const translation power_grid_name
Definition: vehicle.cpp:141
static const int MAX_WIRE_VEHICLE_SIZE
Definition: vehicle.cpp:146

References _, abs(), add_msg(), add_tag(), debugmsg, flag_WIRING(), get_avatar(), get_bounding_box(), get_map(), avatar::grab(), Character::grab_point, m_bad, max(), MAX_WIRE_VEHICLE_SIZE, merge_vehicle_parts(), min(), name, NONE, bounding_box::p1, bounding_box::p2, pivot_anchor, point, Creature::pos(), pos, power_grid_name, shift_if_needed(), om_direction::size, translation::translated(), turn_dir, map::veh_at(), VEHICLE, point::x, and point::y.

Referenced by link_up_actor::link_to_veh_app(), and place_appliance().

◆ merge_rackable_vehicle()

bool vehicle::merge_rackable_vehicle ( vehicle carry_veh,
const std::vector< int > &  rack_parts 
)

Definition at line 1660 of file vehicle.cpp.

1661 {
1662  for( const vpart_reference &vpr : this->get_any_parts( "BIKE_RACK_VEH" ) ) {
1663  const auto unrackables = find_vehicles_to_unrack( vpr.part_index() );
1664  for( const unrackable_vehicle &unrackable : unrackables ) {
1665  if( unrackable.name == carry_veh->name ) {
1666  debugmsg( "vehicle named %s is already racked on this vehicle", unrackable.name );
1667  return false;
1668  }
1669  }
1670  }
1671 
1672  // Mapping between the old vehicle and new vehicle mounting points
1673  struct mapping {
1674  // All the parts attached to this mounting point
1675  std::vector<int> carry_parts_here;
1676 
1677  // the index where the racking part is on the vehicle with the rack
1678  int rack_part = 0;
1679 
1680  // the mount point we are going to add to the vehicle with the rack
1681  point carry_mount;
1682 
1683  // the mount point on the old vehicle (carry_veh) that will be destroyed
1684  point old_mount;
1685  };
1686  remove_fake_parts( /* cleanup = */ false );
1687  invalidate_towing( true );
1688  // By structs, we mean all the parts of the carry vehicle that are at the structure location
1689  // of the vehicle (i.e. frames)
1690  std::vector<int> carry_veh_structs = carry_veh->all_parts_at_location( part_location_structure );
1691  std::vector<mapping> carry_data;
1692  carry_data.reserve( carry_veh_structs.size() );
1693 
1694  units::angle relative_dir = normalize( carry_veh->face.dir() - face.dir() );
1695  units::angle relative_180 = units::fmod( relative_dir, 180_degrees );
1696  units::angle face_dir_180 = normalize( face.dir(), 180_degrees );
1697 
1698  // if the carrier is skewed N/S and the carried vehicle isn't aligned with
1699  // the carrier, force the carried vehicle to be at a right angle
1700  if( face_dir_180 >= 45_degrees && face_dir_180 <= 135_degrees ) {
1701  if( relative_180 >= 45_degrees && relative_180 <= 135_degrees ) {
1702  if( relative_dir < 180_degrees ) {
1703  relative_dir = 90_degrees;
1704  } else {
1705  relative_dir = 270_degrees;
1706  }
1707  }
1708  }
1709 
1710  // We look at each of the structure parts (mount points, i.e. frames) for the
1711  // carry vehicle and then find a rack part adjacent to it. If we don't find a rack part,
1712  // then we can't merge.
1713  bool found_all_parts = true;
1714  for( const int &carry_part : carry_veh_structs ) {
1715 
1716  // The current position on the original vehicle for this part
1717  tripoint carry_pos = carry_veh->global_part_pos3( carry_part );
1718 
1719  bool merged_part = false;
1720  for( int rack_part : rack_parts ) {
1721  size_t j = 0;
1722  // There's no mathematical transform from global pos3 to vehicle mount, so search for the
1723  // carry part in global pos3 after translating
1724  point carry_mount;
1725  for( const point &offset : four_cardinal_directions ) {
1726  carry_mount = parts[ rack_part ].mount + offset;
1727  tripoint possible_pos = mount_to_tripoint( carry_mount );
1728  if( possible_pos == carry_pos ) {
1729  break;
1730  }
1731  ++j;
1732  }
1733 
1734  // We checked the adjacent points from the mounting rack and managed
1735  // to find the current structure part were looking for nearby. If the part was not
1736  // near this particular rack, we would look at each in the list of rack_parts
1737  const bool carry_part_next_to_this_rack = j < four_adjacent_offsets.size();
1738  if( carry_part_next_to_this_rack ) {
1739  mapping carry_map;
1740  point old_mount = carry_veh->parts[ carry_part ].mount;
1741  carry_map.carry_parts_here = carry_veh->parts_at_relative( old_mount, true );
1742  carry_map.rack_part = rack_part;
1743  carry_map.carry_mount = carry_mount;
1744  carry_map.old_mount = old_mount;
1745  carry_data.push_back( carry_map );
1746  merged_part = true;
1747  break;
1748  }
1749  }
1750 
1751  // We checked all the racks and could not find a place for this structure part.
1752  if( !merged_part ) {
1753  found_all_parts = false;
1754  break;
1755  }
1756  }
1757 
1758  // Now that we have mapped all the parts of the carry vehicle to the vehicle with the rack
1759  // we can go ahead and merge
1760  if( found_all_parts ) {
1761  decltype( loot_zones ) new_zones;
1762  for( const mapping &carry_map : carry_data ) {
1763  for( const int &carry_part : carry_map.carry_parts_here ) {
1764  parts.push_back( carry_veh->parts[ carry_part ] );
1765  vehicle_part &carried_part = parts.back();
1766  carried_part.mount = carry_map.carry_mount;
1767  carried_part.carried_stack.push( {
1768  tripoint( carry_map.old_mount, 0 ),
1769  relative_dir,
1770  carry_veh->name
1771  } );
1772  carried_part.enabled = false;
1773  carried_part.set_flag( vp_flag::carried_flag );
1774  //give each carried part a tracked_flag so that we can re-enable overmap tracking on unloading if necessary
1775  if( carry_veh->tracking_on ) {
1776  carried_part.set_flag( vp_flag::tracked_flag );
1777  }
1778 
1779  if( carried_part.has_flag( vp_flag::passenger_flag ) ) {
1780  carried_part.remove_flag( vp_flag::passenger_flag );
1781  carried_part.passenger_id = character_id();
1782  }
1783 
1784  parts[ carry_map.rack_part ].set_flag( vp_flag::carrying_flag );
1785  }
1786 
1787  const std::pair<std::unordered_multimap<point, zone_data>::iterator, std::unordered_multimap<point, zone_data>::iterator>
1788  zones_on_point = carry_veh->loot_zones.equal_range( carry_map.old_mount );
1789  for( std::unordered_multimap<point, zone_data>::const_iterator it = zones_on_point.first;
1790  it != zones_on_point.second; ++it ) {
1791  new_zones.emplace( carry_map.carry_mount, it->second );
1792  }
1793  }
1794 
1795  for( auto &new_zone : new_zones ) {
1797  *this, new_zone.first, new_zone.second );
1798  }
1799 
1800  // Now that we've added zones to this vehicle, we need to make sure their positions
1801  // update when we next interact with them
1802  zones_dirty = true;
1803  remove_fake_parts( /* cleanup = */ true );
1804  refresh();
1805 
1806  map &here = get_map();
1807  //~ %1$s is the vehicle being loaded onto the bicycle rack
1808  add_msg( _( "You load the %1$s on the rack." ), carry_veh->name );
1809  here.destroy_vehicle( carry_veh );
1810  here.dirty_vehicle_list.insert( this );
1813  here.invalidate_map_cache( here.get_abs_sub().z() );
1815  } else {
1816  //~ %1$s is the vehicle being loaded onto the bicycle rack
1817  add_msg( m_bad, _( "You can't get the %1$s on the rack." ), carry_veh->name );
1818  }
1819  return found_all_parts;
1820 }
constexpr auto z() const
Definition: coordinates.h:167
void set_transparency_cache_dirty(int zlev)
Sets a dirty flag on the a given cache.
Definition: map.cpp:273
void rebuild_vehicle_level_caches()
Definition: map.cpp:443
void set_seen_cache_dirty(const tripoint &change_location)
Definition: map.cpp:291
void invalidate_map_cache(int zlev)
Definition: map.cpp:375
tripoint_abs_sm get_abs_sub() const
return abs_sub
Definition: map.cpp:9663
std::set< vehicle * > dirty_vehicle_list
Definition: map.h:1861
tripoint mount_to_tripoint(const point &mount) const
Definition: vehicle.cpp:3326
bool zones_dirty
Definition: vehicle.h:2371
void create_vehicle_loot_zone(class vehicle &vehicle, const point &mount_point, zone_data &new_zone, map *pmap=nullptr)
Definition: clzones.cpp:1373
quantity< V, U > fmod(quantity< V, U > num, quantity< V, U > den)
Definition: units.h:153
character_id passenger_id
ID of player passenger.
Definition: vehicle.h:510
void set_flag(const vp_flag flag) noexcept
Definition: vehicle.h:280
std::stack< carried_part_data > carried_stack
Definition: vehicle.h:303
@ tracked_flag

References _, add_msg(), all_parts_at_location(), carried_flag, vehicle_part::carried_stack, carrying_flag, character_id, zone_manager::create_vehicle_loot_zone(), debugmsg, map::destroy_vehicle(), tileray::dir(), map::dirty_vehicle_list, vehicle_part::enabled, face, find_vehicles_to_unrack(), units::fmod(), four_adjacent_offsets, four_cardinal_directions, map::get_abs_sub(), get_any_parts(), zone_manager::get_manager(), get_map(), global_part_pos3(), vehicle_part::has_flag(), map::invalidate_map_cache(), invalidate_towing(), loot_zones, m_bad, vehicle_part::mount, mount_to_tripoint(), name, normalize(), part_location_structure(), parts, parts_at_relative(), passenger_flag, vehicle_part::passenger_id, map::rebuild_vehicle_level_caches(), refresh(), remove_fake_parts(), vehicle_part::remove_flag(), vehicle_part::set_flag(), map::set_seen_cache_dirty(), map::set_transparency_cache_dirty(), sm_pos, tracked_flag, tracking_on, tripoint, tripoint_zero, coords::coord_point_mut< Point, Subpoint, InBounds >::z(), tripoint::z, and zones_dirty.

Referenced by bikerack_racking_activity_actor::finish().

◆ merge_vehicle_parts()

bool vehicle::merge_vehicle_parts ( vehicle veh)

Definition at line 1822 of file vehicle.cpp.

1823 {
1824  map &here = get_map();
1825  for( const vehicle_part &part : veh->parts ) {
1826  if( part.is_fake || part.removed ) {
1827  continue;
1828  }
1830  // Disconnect cables that are attached between the merging vehicles.
1831  // Delete power cords, drop extension cords on the ground.
1832  item drop = veh->part_to_item( part );
1833  if( drop.link().t_veh.get() == this ) {
1834  if( !veh->magic && part.info().id != vpart_power_cord ) {
1835  const tripoint drop_pos = veh->global_part_pos3( part );
1836  drop.reset_link( false, nullptr, -1, true, drop_pos );
1837  here.add_item_or_charges( drop_pos, drop );
1838  }
1839  veh->remove_remote_part( part );
1840  continue;
1841  }
1842  }
1843  point part_loc = veh->mount_to_tripoint( part.mount ).xy();
1844 
1846  parts.push_back( part );
1847  vehicle_part &copied_part = parts.back();
1848  copied_part.mount = part_loc - global_pos3().xy();
1849 
1850  refresh();
1851  }
1852 
1853  here.destroy_vehicle( veh );
1854 
1855  return true;
1856 }
T * get() const
static const vpart_id vpart_power_cord("power_cord")

References map::add_item_or_charges(), map::destroy_vehicle(), safe_reference< T >::get(), get_map(), global_part_pos3(), global_pos3(), vpart_info::has_flag(), vpart_info::id, vehicle_part::info(), vehicle_part::is_fake, item::link(), magic, vehicle_part::mount, mount_to_tripoint(), part(), part_to_item(), parts, refresh(), remove_fake_parts(), remove_remote_part(), vehicle_part::removed, item::reset_link(), item::link_data::t_veh, vpart_power_cord, VPFLAG_POWER_TRANSFER, and tripoint::xy().

Referenced by merge_appliance_into_grid().

◆ mod_hp()

bool vehicle::mod_hp ( vehicle_part pt,
int  qty 
)

Apply damage to part constrained by range [0,durability] possibly destroying it.

Parameters
ptPart being damaged
qtymaximum amount by which to adjust damage (negative permissible)
Returns
whether part was destroyed as a result of the damage

Definition at line 653 of file vehicle_part.cpp.

654 {
655  const int dur = pt.info().durability;
656  if( dur <= 0 ) {
657  return false;
658  }
659  return pt.base.mod_damage( -qty * pt.base.max_damage() / dur );
660 }
int max_damage() const
Definition: item.cpp:8900
bool mod_damage(int qty)
Apply damage to const itemrained by min_damage and max_damage.
Definition: item.cpp:8927
time_duration dur
Definition: creature.h:237

References vehicle_part::base, dur, vpart_info::durability, vehicle_part::info(), item::max_damage(), and item::mod_damage().

Referenced by damage_direct(), explode_fuel(), and smash().

◆ mount_to_tripoint() [1/2]

tripoint vehicle::mount_to_tripoint ( const point mount) const

◆ mount_to_tripoint() [2/2]

tripoint vehicle::mount_to_tripoint ( const point mount,
const point offset 
) const

Definition at line 3331 of file vehicle.cpp.

3332 {
3333  tripoint mnt_translated;
3334  coord_translate( pivot_rotation[0], pivot_anchor[ 0 ], mount + offset, mnt_translated );
3335  return global_pos3() + mnt_translated;
3336 }

References coord_translate(), global_pos3(), pivot_anchor, and pivot_rotation.

◆ move_vec()

rl_vec2d vehicle::move_vec ( ) const

Definition at line 1607 of file vehicle_move.cpp.

1608 {
1609  return angle_to_vec( move.dir() );
1610 }

References angle_to_vec(), tileray::dir(), and move.

Referenced by game::calc_driving_offset(), forward_velocity(), possibly_recover_from_skid(), and velo_vec().

◆ net_battery_charge_rate()

units::power vehicle::net_battery_charge_rate ( bool  include_reactors) const

Definition at line 5157 of file vehicle.cpp.

5158 {
5161  linked_item_epower_this_turn + ( include_reactors ? active_reactor_epower() : 0_W );
5162 }
units::power total_solar_epower() const
Definition: vehicle.cpp:5096
units::power total_wind_epower() const
Definition: vehicle.cpp:5116
units::power total_accessory_epower() const
Definition: vehicle.cpp:4998
units::power total_alternator_epower() const
Definition: vehicle.cpp:5063
units::power active_reactor_epower() const
Definition: vehicle.cpp:5164
units::power total_engine_epower() const
Definition: vehicle.cpp:5078
units::power total_water_wheel_epower() const
Definition: vehicle.cpp:5140

References active_reactor_epower(), linked_item_epower_this_turn, total_accessory_epower(), total_alternator_epower(), total_engine_epower(), total_solar_epower(), total_water_wheel_epower(), and total_wind_epower().

Referenced by active_reactor_epower(), veh_interact::calc_overview(), print_fuel_indicator(), and smart_controller_handle_turn().

◆ next_part_to_close()

int vehicle::next_part_to_close ( int  p,
bool  outside = false 
) const

Return the index of the next part to close at p

The next part to open is the first opened part in the list of parts at part p's coordinates. Returns -1 for no more to close.

Parameters
pPart who's coordinates provide the location to check
outsideIf true, give parts that can be closed from outside only
Returns
part index or -1 if no part

Definition at line 2928 of file vehicle.cpp.

2929 {
2930  std::vector<int> parts_here = parts_at_relative( parts[p].mount, true, true );
2931 
2932  // We want reverse, since we close the innermost thing first (door), and then the outermost thing (curtains)
2933  for( std::vector<int>::reverse_iterator part_it = parts_here.rbegin();
2934  part_it != parts_here.rend();
2935  ++part_it ) {
2936  const vehicle_part &vp = part( *part_it );
2937  const vpart_info &vpi = vp.info();
2938  if( vpi.has_flag( VPFLAG_OPENABLE ) && vp.is_available() && vp.open == 1
2939  && ( !outside || !vpi.has_flag( "OPENCLOSE_INSIDE" ) ) ) {
2940  return *part_it;
2941  }
2942  }
2943  return -1;
2944 }

References vpart_info::has_flag(), vehicle_part::info(), vehicle_part::is_available(), vehicle_part::open, part(), parts, parts_at_relative(), and VPFLAG_OPENABLE.

Referenced by doors::close_door(), and control_doors().

◆ next_part_to_lock()

int vehicle::next_part_to_lock ( int  p,
bool  outside = false 
) const

Return the index of the next part to lock at part p's location.

The next part to lock is the first closed, unlocked part in the list of parts at part p's coordinates with the lockable_door flag.

Parameters
ppart whose coordinates provide the location to check
outsideif true, give parts that can be locked from outside only
Returns
a part index or -1 if no part

Definition at line 2974 of file vehicle.cpp.

2975 {
2976  if( !part_has_lock( p ) ) {
2977  return -1;
2978  }
2979  std::vector<int> parts_here = parts_at_relative( parts[p].mount, true, true );
2980  // We want reverse, since we lock the innermost thing first (door), and then the outermost thing
2981  for( std::vector<int>::reverse_iterator part_it = parts_here.rbegin();
2982  part_it != parts_here.rend();
2983  ++part_it ) {
2984  const vehicle_part &vp = part( *part_it );
2985  if( vp.info().has_flag( "LOCKABLE_DOOR" ) && vp.is_available() &&
2986  vp.open == 0 && !vp.locked && !outside ) {
2987  return *part_it;
2988  }
2989  }
2990  return -1;
2991 }
bool part_has_lock(int part_index) const
Definition: vehicle.cpp:2963

References vpart_info::has_flag(), vehicle_part::info(), vehicle_part::is_available(), vehicle_part::locked, vehicle_part::open, part(), part_has_lock(), parts, and parts_at_relative().

Referenced by doors::can_lock_door(), control_doors(), doors::lock_door(), and doors::unlock_door().

◆ next_part_to_open()

int vehicle::next_part_to_open ( int  p,
bool  outside = false 
) const

Return the index of the next part to open at p's location.

The next part to open is the first unopened part in the reversed list of parts at part p's coordinates.

Parameters
pPart who's coordinates provide the location to check
outsideIf true, give parts that can be opened from outside only
Returns
part index or -1 if no part

Definition at line 2946 of file vehicle.cpp.

2947 {
2948  const bool has_lock = part_has_lock( p );
2949  // We want forwards, since we open the outermost thing first (curtains), and then the innermost thing (door)
2950 
2951  for( const int elem : parts_at_relative( parts[p].mount, true, true ) ) {
2952  const vehicle_part &vp = part( elem );
2953  const vpart_info &vpi = vp.info();
2954  if( vpi.has_flag( VPFLAG_OPENABLE ) && vp.is_available() && vp.open == 0 &&
2955  !( vp.locked && has_lock ) &&
2956  ( !outside || !vpi.has_flag( "OPENCLOSE_INSIDE" ) ) ) {
2957  return elem;
2958  }
2959  }
2960  return -1;
2961 }

References vpart_info::has_flag(), vehicle_part::info(), vehicle_part::is_available(), vehicle_part::locked, vehicle_part::open, part(), part_has_lock(), parts, parts_at_relative(), and VPFLAG_OPENABLE.

Referenced by doors::close_door(), control_doors(), avatar_action::move(), open(), and map::route().

◆ next_part_to_unlock()

int vehicle::next_part_to_unlock ( int  p,
bool  outside = false 
) const

Return the index of the next part to unlock at part p's location.

The next part to unlock is the first locked part in the list of parts at part p's coordinates with the lockable_door flag.

Parameters
ppart whose coordinates provide the location to check
outsideif true, give parts that can be unlocked from outside only
Returns
part index or -1 if no part

Definition at line 2993 of file vehicle.cpp.

2994 {
2995  if( !part_has_lock( p ) ) {
2996  return -1;
2997  }
2998  for( const int elem : parts_at_relative( parts[p].mount, true, true ) ) {
2999  const vehicle_part &vp = part( elem );
3000  if( vp.info().has_flag( "LOCKABLE_DOOR" ) && vp.is_available() && vp.locked && !outside ) {
3001  return elem;
3002  }
3003  }
3004  return -1;
3005 }

References vpart_info::has_flag(), vehicle_part::info(), vehicle_part::is_available(), vehicle_part::locked, part(), part_has_lock(), parts, and parts_at_relative().

Referenced by doors::can_unlock_door(), can_unmount(), control_doors(), doors::lock_door(), map::route(), and doors::unlock_door().

◆ no_towing_slack()

bool vehicle::no_towing_slack ( ) const

Definition at line 6919 of file vehicle.cpp.

6920 {
6921  if( !tow_data.get_towed() ) {
6922  return false;
6923  }
6924  int index = get_tow_part();
6925  if( index == -1 ) {
6926  debugmsg( "towing data exists but no towing part" );
6927  return false;
6928  }
6929  map &here = get_map();
6930  tripoint towing_point = here.getabs( global_part_pos3( index ) );
6931  if( !tow_data.get_towed()->tow_data.get_towed_by() ) {
6932  debugmsg( "vehicle %s has data for a towed vehicle, but that towed vehicle does not have %s listed as tower",
6933  disp_name(), disp_name() );
6934  return false;
6935  }
6936  int other_index = tow_data.get_towed()->get_tow_part();
6937  if( other_index == -1 ) {
6938  debugmsg( "towing data exists but no towing part" );
6939  return false;
6940  }
6941  tripoint towed_point = here.getabs( tow_data.get_towed()->global_part_pos3( other_index ) );
6942  if( towing_point == tripoint_zero || towed_point == tripoint_zero ) {
6943  debugmsg( "towing data exists but no towing part" );
6944  return false;
6945  }
6946  return rl_dist( towing_point, towed_point ) >= 8;
6947 
6948 }

References debugmsg, disp_name(), get_map(), get_tow_part(), towing_data::get_towed(), towing_data::get_towed_by(), map::getabs(), global_part_pos3(), rl_dist(), tow_data, and tripoint_zero.

Referenced by do_towing_move().

◆ noise_and_smoke()

void vehicle::noise_and_smoke ( int  load,
time_duration  time = 1_turns 
)

Generate noise or smoke from a vehicle with engines turned on load = how hard the engines are working, from 0.0 until 1.0 time = how many seconds to generated smoke for.

TODO: handle other engine types: muscle / animal / wind / coal / ...

Definition at line 4018 of file vehicle.cpp.

4019 {
4020  static const std::array<std::pair<std::string, int>, 8> sounds = { {
4021  { translate_marker( "hmm" ), 0 }, { translate_marker( "hummm!" ), 15 },
4022  { translate_marker( "whirrr!" ), 30 }, { translate_marker( "vroom!" ), 60 },
4023  { translate_marker( "roarrr!" ), 100 }, { translate_marker( "ROARRR!" ), 140 },
4024  { translate_marker( "BRRROARRR!" ), 180 }, { translate_marker( "BRUMBRUMBRUMBRUM!" ), INT_MAX }
4025  }
4026  };
4027  const std::string heli_noise = translate_marker( "WUMPWUMPWUMP!" );
4028  double noise = 0.0;
4029  double mufflesmoke = 0.0;
4030  double muffle;
4031  int exhaust_part;
4032  std::tie( exhaust_part, muffle ) = get_exhaust_part();
4033 
4034  bool bad_filter = false;
4035  bool combustion = false;
4036 
4037  this->vehicle_noise = 0; // reset noise, in case all combustion engines are dead
4038  for( const int p : engines ) {
4039  const vehicle_part &vp = parts[p];
4040  if( engine_on && is_engine_on( vp ) && engine_fuel_left( vp ) ) {
4041  // convert current engine load to units of watts/40K
4042  // then spew more smoke and make more noise as the engine load increases
4043  int part_watts = units::to_watt( part_vpower_w( vp, true ) );
4044  double max_stress = static_cast<double>( part_watts / 40000.0 );
4045  double cur_stress = load / 1000.0 * max_stress;
4046  // idle stress = 1.0 resulting in nominal working engine noise = engine_noise_factor()
4047  // and preventing noise = 0
4048  cur_stress = std::max( cur_stress, 1.0 );
4049  double part_noise = cur_stress * vp.info().engine_info->noise_factor;
4050 
4051  if( is_engine_type_combustion( vp ) ) {
4052  combustion = true;
4053  double health = vp.health_percent();
4054  if( vp.has_fault_flag( "ENG_BACKFIRE" ) ) {
4055  health = 0.0;
4056  }
4057  if( health < vp.info().engine_info->backfire_threshold && one_in( 50 + 150 * health ) ) {
4058  backfire( vp );
4059  }
4060  double j = cur_stress * to_turns<int>( time ) * muffle * 1000;
4061 
4062  if( vp.has_fault_flag( "EXTRA_EXHAUST" ) ) {
4063  bad_filter = true;
4064  j *= j;
4065  }
4066 
4067  if( ( exhaust_part == -1 ) && engine_on ) {
4068  spew_field( j, p, fd_smoke, bad_filter ? fd_smoke->get_max_intensity() : 1 );
4069  } else {
4070  mufflesmoke += j;
4071  }
4072  part_noise = ( part_noise + max_stress * 3 + 5 ) * muffle;
4073  }
4074  noise = std::max( noise, part_noise ); // Only the loudest engine counts.
4075  }
4076  }
4077  if( !combustion ) {
4078  return;
4079  }
4080  /// TODO: handle other engine types: muscle / animal / wind / coal / ...
4081 
4082  if( exhaust_part != -1 && engine_on ) {
4083  spew_field( mufflesmoke, exhaust_part, fd_smoke,
4084  bad_filter ? fd_smoke->get_max_intensity() : 1 );
4085  }
4086  if( is_rotorcraft() ) {
4087  noise *= 2;
4088  }
4089  // Cap engine noise to avoid deafening.
4090  noise = std::min( noise, 100.0 );
4091  // Even a vehicle with engines off will make noise traveling at high speeds
4092  noise = std::max( noise, static_cast<double>( std::fabs( velocity / 500.0 ) ) );
4093  int lvl = 0;
4094  if( one_in( 4 ) && rng( 0, 30 ) < noise ) {
4095  while( noise > sounds[lvl].second ) {
4096  lvl++;
4097  }
4098  }
4099  add_msg_debug( debugmode::DF_VEHICLE, "VEH NOISE final: %d", static_cast<int>( noise ) );
4100  vehicle_noise = static_cast<unsigned char>( noise );
4102  _( is_rotorcraft() ? heli_noise : sounds[lvl].first ), true );
4103 }
bool is_engine_type_combustion(const vehicle_part &vp) const
Definition: vehicle.cpp:1005
void spew_field(double joules, int part, field_type_id type, int intensity=1) const
Definition: vehicle.cpp:4003
void backfire(const vehicle_part &vp) const
Definition: vehicle.cpp:1064
const field_type_str_id fd_smoke("fd_smoke")
Definition: sounds.h:22
quantity< V, U > fabs(quantity< V, U > q)
Definition: units.h:147
int get_max_intensity() const
Definition: field_type.h:256
#define translate_marker(x)
Marks a string literal to be extracted for translation.
Definition: translations.h:17

References _, add_msg_debug, backfire(), debugmode::DF_VEHICLE, engine_fuel_left(), vpart_info::engine_info, engine_on, engines, units::fabs(), fd_smoke, get_exhaust_part(), field_type::get_max_intensity(), global_pos3(), vehicle_part::has_fault_flag(), health, vehicle_part::health_percent(), vehicle_part::info(), is_engine_on(), is_engine_type_combustion(), is_rotorcraft(), ammo_effects::load(), max(), min(), sounds::movement, noise, one_in(), part_vpower_w(), parts, rng(), second, sounds::sound(), spew_field(), units::to_watt(), translate_marker, vehicle_noise, and velocity.

Referenced by idle(), power_parts(), and thrust().

◆ on_move()

void vehicle::on_move ( )

Definition at line 5726 of file vehicle.cpp.

5727 {
5728  if( has_part( "TRANSFORM_TERRAIN", true ) ) {
5730  }
5731  if( has_part( "SCOOP", true ) ) {
5732  operate_scoop();
5733  }
5734  if( has_part( "PLANTER", true ) ) {
5735  operate_planter();
5736  }
5737  if( has_part( "REAPER", true ) ) {
5738  operate_reaper();
5739  }
5740 
5743  is_passenger( pc ), player_in_control( pc ), remote_controlled( pc ),
5745  is_falling, is_in_water( true ) && !can_float(),
5747  );
5748 }
void operate_reaper()
void operate_planter()
bool is_passenger(Character &c) const
Definition: vehicle.cpp:3389
void transform_terrain()
void operate_scoop()
bool is_in_water(bool deep_water=false) const
is the vehicle mostly in water or mostly on fairly dry land?
Definition: vehicle.cpp:4462
bool remote_controlled(const Character &p) const
Definition: vehicle.cpp:274

References can_float(), can_use_rails(), get_event_bus(), get_player_character(), has_part(), is_falling, is_flying_in_air(), is_in_water(), is_passenger(), is_watercraft(), operate_planter(), operate_reaper(), operate_scoop(), player_in_control(), remote_controlled(), event_bus::send(), skidding, sm_pos, transform_terrain(), vehicle_moves, velocity, and tripoint::z.

Referenced by map::move_vehicle().

◆ open()

void vehicle::open ( int  part_index)

Opens an openable part at the specified index.

If it's a multipart, opens all attached parts as well.

Parameters
part_indexThe index in the parts list of the part to open.

Definition at line 1195 of file vehicle_use.cpp.

1196 {
1197  vehicle_part &vp = part( part_index );
1198  if( !vp.info().has_flag( VPFLAG_OPENABLE ) ) {
1199  debugmsg( "Attempted to open non-openable part %d (%s) on a %s!", part_index, vp.name(), name );
1200  } else {
1201  open_or_close( part_index, true );
1202  }
1203 }

References debugmsg, vpart_info::has_flag(), vehicle_part::info(), vehicle_part::name(), name, open_or_close(), part(), and VPFLAG_OPENABLE.

Referenced by control_doors(), init_state(), avatar_action::move(), open(), and open_all_at().

◆ open_all_at()

void vehicle::open_all_at ( int  p)

Opens everything that can be opened on the same tile as p

Definition at line 1289 of file vehicle_use.cpp.

1290 {
1291  for( const int elem : parts_at_relative( parts[p].mount, true, true ) ) {
1292  const vehicle_part &vp = parts[elem];
1293  if( vp.info().has_flag( VPFLAG_OPENABLE ) ) {
1294  // Note that this will open multi-square and non-multipart parts in the tile. This
1295  // means that adjacent open multi-square openables can still have closed stuff
1296  // on same tile after this function returns
1297  open( elem );
1298  }
1299  }
1300 }

References vpart_info::has_flag(), vehicle_part::info(), open(), parts, parts_at_relative(), and VPFLAG_OPENABLE.

Referenced by avatar_action::move(), and open().

◆ open_or_close()

void vehicle::open_or_close ( int  part_index,
bool  opening 
)
private

Opens or closes an openable part at the specified index based on the @opening value passed.

If it's a multipart, opens or closes all attached parts as well.

Parameters
part_indexThe index in the parts list of the part to open or close.

Definition at line 1307 of file vehicle_use.cpp.

1308 {
1309  const auto part_open_or_close = [&]( const int parti, const bool opening ) {
1310  vehicle_part &prt = parts.at( parti );
1311  // Open doors should never be locked.
1312  if( opening && prt.locked ) {
1313  unlock( parti );
1314  }
1315  prt.open = opening;
1316  if( prt.is_fake ) {
1317  parts.at( prt.fake_part_to ).open = opening;
1318  } else if( prt.has_fake ) {
1319  parts.at( prt.fake_part_at ).open = opening;
1320  }
1321  };
1322  //find_lines_of_parts() doesn't return the part_index we passed, so we set it on its own
1323  part_open_or_close( part_index, opening );
1324  insides_dirty = true;
1325  map &here = get_map();
1327  const tripoint part_location = mount_to_tripoint( parts[part_index].mount );
1328  here.set_seen_cache_dirty( part_location );
1329  const int dist = rl_dist( get_player_character().pos(), part_location );
1330  if( dist < 20 ) {
1331  sfx::play_variant_sound( opening ? "vehicle_open" : "vehicle_close",
1332  parts[ part_index ].info().id.str(), 100 - dist * 3 );
1333  }
1334  for( const std::vector<int> &vec : find_lines_of_parts( part_index, "OPENABLE" ) ) {
1335  for( const int &partID : vec ) {
1336  part_open_or_close( partID, opening );
1337  }
1338  }
1339 
1340  coeff_air_changed = true;
1341  coeff_air_dirty = true;
1342 }
void unlock()
Definition: vehicle.cpp:1051
void play_variant_sound(const std::string &id, const std::string &variant, int volume, units::angle angle, double pitch_min=-1.0, double pitch_max=-1.0)
Definition: sounds.cpp:1999

References coeff_air_changed, coeff_air_dirty, vehicle_part::fake_part_at, vehicle_part::fake_part_to, find_lines_of_parts(), get_map(), get_player_character(), vehicle_part::has_fake, insides_dirty, vehicle_part::is_fake, vehicle_part::locked, mount_to_tripoint(), vehicle_part::open, parts, sfx::play_variant_sound(), pos, rl_dist(), map::set_seen_cache_dirty(), map::set_transparency_cache_dirty(), sm_pos, unlock(), and tripoint::z.

Referenced by close(), control_doors(), and open().

◆ operate_planter()

void vehicle::operate_planter ( )

Definition at line 1072 of file vehicle_use.cpp.

1073 {
1074  map &here = get_map();
1075  for( const vpart_reference &vp : get_enabled_parts( "PLANTER" ) ) {
1076  const size_t planter_id = vp.part_index();
1077  const tripoint loc = vp.pos();
1078  vehicle_stack v = get_items( vp.part() );
1079  for( auto i = v.begin(); i != v.end(); i++ ) {
1080  if( i->is_seed() ) {
1081  // If it is an "advanced model" then it will avoid damaging itself or becoming damaged. It's a real feature.
1082  if( here.ter( loc ) != ter_t_dirtmound && vp.has_feature( "ADVANCED_PLANTER" ) ) {
1083  //then don't put the item there.
1084  break;
1085  } else if( here.ter( loc ) == ter_t_dirtmound ) {
1086  here.set( loc, ter_t_dirt, furn_f_plant_seed );
1087  } else if( !here.has_flag( ter_furn_flag::TFLAG_PLOWABLE, loc ) ) {
1088  //If it isn't plowable terrain, then it will most likely be damaged.
1089  damage( here, planter_id, rng( 1, 10 ), damage_bash, false );
1090  sounds::sound( loc, rng( 10, 20 ), sounds::sound_t::combat, _( "Clink" ), false, "smash_success",
1091  "hit_vehicle" );
1092  }
1093  if( !i->count_by_charges() || i->charges == 1 ) {
1094  i->set_age( 0_turns );
1095  here.add_item( loc, *i );
1096  v.erase( i );
1097  } else {
1098  item tmp = *i;
1099  tmp.charges = 1;
1100  tmp.set_age( 0_turns );
1101  here.add_item( loc, tmp );
1102  i->charges--;
1103  }
1104  break;
1105  }
1106  }
1107  }
1108 }
iterator begin()
Definition: item_stack.cpp:32
iterator end()
Definition: item_stack.cpp:37
void set_age(const time_duration &age)
Definition: item.cpp:14681
void set(const tripoint &p, const ter_id &new_terrain, const furn_id &new_furniture)
Definition: map.cpp:1678
ter_id ter(const tripoint &p) const
Definition: map.cpp:1922
item & add_item(const tripoint &p, item new_item, int copies)
Place an item on the map, despite the parameter name, this is not necessarily a new item.
Definition: map.cpp:5329
item_stack::iterator erase(item_stack::const_iterator it) override
Definition: vehicle.cpp:187
int damage(map &here, int p, int dmg, const damage_type_id &type=damage_type_id("bash"), bool aimed=true)
Definition: vehicle.cpp:7143
static const damage_type_id damage_bash("bash")
static const ter_str_id ter_t_dirt("t_dirt")
static const furn_str_id furn_f_plant_seed("f_plant_seed")
static const ter_str_id ter_t_dirtmound("t_dirtmound")

References _, map::add_item(), item_stack::begin(), item::charges, sounds::combat, damage(), damage_bash, item_stack::end(), vehicle_stack::erase(), furn_f_plant_seed, get_enabled_parts(), get_items(), get_map(), map::has_flag(), rng(), map::set(), item::set_age(), sounds::sound(), map::ter(), ter_t_dirt, ter_t_dirtmound, and TFLAG_PLOWABLE.

Referenced by on_move().

◆ operate_reaper()

void vehicle::operate_reaper ( )

Definition at line 1028 of file vehicle_use.cpp.

1029 {
1030  map &here = get_map();
1031  for( const vpart_reference &vp : get_enabled_parts( "REAPER" ) ) {
1032  const tripoint reaper_pos = vp.pos();
1033  const int plant_produced = rng( 1, vp.info().bonus );
1034  const int seed_produced = rng( 1, 3 );
1035  const units::volume max_pickup_volume = vp.info().size / 20;
1036  if( here.furn( reaper_pos ) != furn_f_plant_harvest ) {
1037  continue;
1038  }
1039  // Can't use item_stack::only_item() since there might be fertilizer
1040  map_stack items = here.i_at( reaper_pos );
1041  map_stack::iterator seed = std::find_if( items.begin(), items.end(), []( const item & it ) {
1042  return it.is_seed();
1043  } );
1044  if( seed == items.end() || seed->typeId() == itype_fungal_seeds ||
1045  seed->typeId() == itype_marloss_seed ) {
1046  // Otherworldly plants, the earth-made reaper can not handle those.
1047  continue;
1048  }
1049  here.furn_set( reaper_pos, furn_str_id::NULL_ID() );
1050  // Secure the seed type before i_clear destroys the item.
1051  const itype &seed_type = *seed->type;
1052  here.i_clear( reaper_pos );
1054  seed_type, plant_produced, seed_produced, false ) ) {
1055  here.add_item_or_charges( reaper_pos, i );
1056  }
1057  sounds::sound( reaper_pos, rng( 10, 25 ), sounds::sound_t::combat, _( "Swish" ), false, "vehicle",
1058  "reaper" );
1059  if( vp.info().has_flag( VPFLAG_CARGO ) ) {
1060  for( map_stack::iterator iter = items.begin(); iter != items.end(); ) {
1061  if( ( iter->volume() <= max_pickup_volume ) &&
1062  add_item( vp.part(), *iter ) ) {
1063  iter = items.erase( iter );
1064  } else {
1065  ++iter;
1066  }
1067  }
1068  }
1069  }
1070 }
Definition: map.h:107
iterator erase(const_iterator it) override
Definition: map.cpp:219
bool furn_set(const tripoint &p, const furn_id &new_furniture, bool furn_reset=false, bool avoid_creatures=false)
furn_reset should be true if new_furniture is being set to f_null when the player is grab-moving furn...
Definition: map.cpp:1743
map_stack i_at(const tripoint &p)
Definition: map.cpp:4978
void i_clear(const tripoint &p)
Definition: map.cpp:5030
furn_id furn(const tripoint &p) const
Definition: map.cpp:1722
static const string_id< furn_t > & NULL_ID()
Returns a null id whose string_id<T>::is_null() must always return true.
std::list< item > get_harvest_items(const itype &type, int plant_count, int seed_count, bool byproducts)
Items that appear when a generic plant is harvested.
Definition: iexamine.cpp:2592
std::optional< int > seed(Character *, item *, const tripoint &)
Definition: iuse.cpp:5301
static const itype_id itype_fungal_seeds("fungal_seeds")
static const itype_id itype_marloss_seed("marloss_seed")
static const furn_str_id furn_f_plant_harvest("f_plant_harvest")

References _, add_item(), map::add_item_or_charges(), item_stack::begin(), sounds::combat, item_stack::end(), map_stack::erase(), map::furn(), furn_f_plant_harvest, map::furn_set(), get_enabled_parts(), iexamine::get_harvest_items(), get_map(), map::i_at(), map::i_clear(), itype_fungal_seeds, itype_marloss_seed, string_id< furn_t >::NULL_ID(), rng(), iuse::seed(), sounds::sound(), and VPFLAG_CARGO.

Referenced by on_move().

◆ operate_scoop()

void vehicle::operate_scoop ( )

Definition at line 1110 of file vehicle_use.cpp.

1111 {
1112  map &here = get_map();
1113  for( const vpart_reference &vp : get_enabled_parts( "SCOOP" ) ) {
1114  const size_t scoop = vp.part_index();
1115  const int chance_to_damage_item = 9;
1116  const units::volume max_pickup_volume = vp.info().size / 10;
1117  const std::array<std::string, 4> sound_msgs = {{
1118  _( "Whirrrr" ), _( "Ker-chunk" ), _( "Swish" ), _( "Cugugugugug" )
1119  }
1120  };
1122  random_entry_ref( sound_msgs ), false, "vehicle", "scoop" );
1123  std::vector<tripoint> parts_points;
1124  for( const tripoint &current :
1125  here.points_in_radius( global_part_pos3( scoop ), 1 ) ) {
1126  parts_points.push_back( current );
1127  }
1128  for( const tripoint &position : parts_points ) {
1129  // TODO: fix point types
1130  here.mop_spills( tripoint_bub_ms( position ) );
1131  if( !here.has_items( position ) ) {
1132  continue;
1133  }
1134  item *that_item_there = nullptr;
1135  map_stack items = here.i_at( position );
1136  if( here.has_flag( ter_furn_flag::TFLAG_SEALED, position ) ) {
1137  // Ignore it. Street sweepers are not known for their ability to harvest crops.
1138  continue;
1139  }
1140  for( item &it : items ) {
1141  if( it.volume() < max_pickup_volume ) {
1142  that_item_there = &it;
1143  break;
1144  }
1145  }
1146  if( !that_item_there ) {
1147  continue;
1148  }
1149  if( one_in( chance_to_damage_item ) && that_item_there->damage() < that_item_there->max_damage() ) {
1150  //The scoop will not destroy the item, but it may damage it a bit.
1151  that_item_there->inc_damage();
1152  //The scoop gets a lot louder when breaking an item.
1153  sounds::sound( position, rng( 10,
1154  that_item_there->volume() / units::legacy_volume_factor * 2 + 10 ),
1155  sounds::sound_t::combat, _( "BEEEThump" ), false, "vehicle", "scoop_thump" );
1156  }
1157  //This attempts to add the item to the scoop inventory and if successful, removes it from the map.
1158  if( add_item( vp.part(), *that_item_there ) ) {
1159  here.i_rem( position, that_item_there );
1160  } else {
1161  break;
1162  }
1163  }
1164  }
1165 }
units::volume volume(bool integral=false, bool ignore_contents=false, int charges_in_vol=-1) const
Total volume of an item accounting for all contained/integrated items NOTE: Result is rounded up to n...
Definition: item.cpp:7360
bool inc_damage()
Same as mod_damage( itype::damage_scale ), advances item to next damage level.
Definition: item.cpp:8947
int damage() const
How much damage has the item sustained?
Definition: item.cpp:858
bool has_items(const tripoint &p) const
Checks for existence of items.
Definition: map.cpp:5890
map_stack::iterator i_rem(const tripoint &p, const map_stack::const_iterator &it)
Definition: map.cpp:5001
bool mop_spills(const tripoint_bub_ms &p)
Remove moppable fields/items at this location.
Definition: map.cpp:3695

References _, add_item(), sounds::combat, item::damage(), get_enabled_parts(), get_map(), global_part_pos3(), map::has_flag(), map::has_items(), map::i_at(), map::i_rem(), item::inc_damage(), units::legacy_volume_factor, item::max_damage(), map::mop_spills(), one_in(), map::points_in_radius(), random_entry_ref(), rng(), sounds::sound(), TFLAG_SEALED, and item::volume().

Referenced by on_move().

◆ operator=() [1/2]

vehicle& vehicle::operator= ( const vehicle )
privatedefault

◆ operator=() [2/2]

vehicle& vehicle::operator= ( vehicle &&  )
default

◆ part() [1/2]

vehicle_part & vehicle::part ( int  part_num)

Definition at line 8098 of file vehicle.cpp.

8099 {
8100  return parts[part_num];
8101 }

References parts.

Referenced by map::add_splatter(), avail_linkable_part(), avail_part_with_feature(), average_offroad_rating(), break_off(), build_bike_rack_menu(), map::build_seen_cache(), veh_app_interact::can_disconnect(), can_mount(), veh_interact::can_remove_part(), advanced_inv_area::can_store_in_vehicle(), veh_interact::cant_do(), close(), doors::close_door(), coeff_water_drag(), veh_interact::complete_vehicle(), vehicle::autodrive_controller::compute_profile(), control_doors(), damage(), damage_all(), MapExtras::delete_items_at_mount(), map::displace_vehicle(), veh_interact::display_veh(), veh_interact::do_change_shape(), veh_interact::do_remove(), veh_interact::do_repair(), unload_loot_activity_actor::do_turn(), construct::done_vehicle(), map::draw_maptile(), exhaust_dest(), optional_vpart_position::extended_description(), vehicles::finalize_prototypes(), find_lines_of_parts(), find_vehicles_to_unrack(), folding_time(), fuel_left(), generic_multi_activity_check_requirement(), get_connected_vehicles(), get_display_of_tile(), get_exhaust_part(), get_points(), vpart_position::get_tools(), advanced_inv_area::get_vehicle_stack(), game::grabbed_veh_move(), has_quality_from_vpart(), has_security_working(), has_structural_part(), index_of_part(), invalidate_towing(), vpart_position::is_inside(), item::link_to(), lock(), doors::lock_door(), vehicle_part_with_feature_range< feature_type >::matches(), vehicle_part_range::matches(), vehicle_part_with_fakes_range::matches(), max_quality_from_vpart(), merge_vehicle_parts(), map::mop_spills(), vpart_position::mount(), avatar_action::move(), veh_interact::move_cursor(), move_item(), map::move_vehicle(), next_part_to_close(), next_part_to_lock(), next_part_to_open(), next_part_to_unlock(), open(), open(), orient_part(), vpart_reference::part(), part_collision(), part_with_feature(), npc::pick_up_item_vehicle(), place_spawn_items(), pldrive(), veh_app_interact::populate_app_actions(), item::process_link(), process_vehicle_items(), refresh(), refresh_insides(), veh_app_interact::remove(), remove_carried_vehicle(), item_location::impl::item_on_vehicle::remove_item(), remove_remote_part(), DefaultRemovePartHandler::removed(), veh_utils::repair_part(), item::reset_link(), roof_at_part(), map::route(), separate_from_grid(), item_location::impl::item_on_vehicle::serialize(), veh_interact::serialize_activity(), map::shake_vehicle(), shed_loose_parts(), slow_leak(), smash(), smash_security_system(), spew_field(), split_vehicles(), activity_handlers::start_engines_finish(), sufficient_wheel_config(), map::terrain_moppable(), total_accessory_epower(), unfolding_time(), unlink_cables(), unlock(), doors::unlock_door(), item_location::impl::item_on_vehicle::unpack(), veh_interact::update_part_requirements(), use_harness(), use_monster_capture(), vehicle_activity(), display::vehicle_fuel_percent_text_color(), map::vehicle_vehicle_collision(), and map::vehicle_wheel_traction().

◆ part() [2/2]

const vehicle_part & vehicle::part ( int  part_num) const

Definition at line 8103 of file vehicle.cpp.

8104 {
8105  return parts[part_num];
8106 }

References parts.

◆ part_at()

int vehicle::part_at ( const point dp) const

Definition at line 3214 of file vehicle.cpp.

3215 {
3216  for( const vpart_reference &vp : get_all_parts() ) {
3217  if( vp.part().precalc[0].xy() == dp && !vp.part().removed ) {
3218  return static_cast<int>( vp.part_index() );
3219  }
3220  }
3221  return -1;
3222 }

References get_all_parts().

Referenced by get_bounding_box(), item::link_to(), veh_app_interact::plug(), veh_app_interact::populate_app_actions(), item::process_link(), veh_app_interact::remove(), and item::reset_link().

◆ part_base()

item_location vehicle::part_base ( int  p)

Get handle for base item of part.

Definition at line 2553 of file vehicle.cpp.

2554 {
2555  return item_location( vehicle_cursor( *this, p ), &parts[ p ].base );
2556 }

References parts.

Referenced by veh_interact::do_mend().

◆ part_collision()

veh_collision vehicle::part_collision ( int  part,
const tripoint p,
bool  just_detect,
bool  bash_floor 
)

Definition at line 832 of file vehicle_move.cpp.

834 {
835  // Vertical collisions need to be handled differently
836  // All collisions have to be either fully vertical or fully horizontal for now
837  const bool vert_coll = bash_floor || p.z != sm_pos.z;
838  Character &player_character = get_player_character();
839  const bool pl_ctrl = player_in_control( player_character );
840  Creature *critter = get_creature_tracker().creature_at( p, true );
841  Character *ph = dynamic_cast<Character *>( critter );
842 
843  Creature *driver = pl_ctrl ? &player_character : nullptr;
844 
845  // If in a vehicle assume it's this one
846  if( ph != nullptr && ph->in_vehicle ) {
847  critter = nullptr;
848  ph = nullptr;
849  }
850 
851  map &here = get_map();
852  const optional_vpart_position ovp = here.veh_at( p );
853  // Disable vehicle/critter collisions when bashing floor
854  // TODO: More elegant code
855  const bool is_veh_collision = !bash_floor && ovp && &ovp->vehicle() != this;
856  const bool is_body_collision = !bash_floor && critter != nullptr;
857 
859  ret.type = veh_coll_nothing;
860  ret.part = part;
861 
862  // Vehicle collisions are a special case. just return the collision.
863  // The map takes care of the dynamic stuff.
864  if( is_veh_collision ) {
865  ret.type = veh_coll_veh;
866  //"imp" is too simplistic for vehicle-vehicle collisions
867  ret.target = &ovp->vehicle();
868  ret.target_part = ovp->part_index();
869  ret.target_name = ovp->vehicle().disp_name();
870  return ret;
871  }
872 
873  // Typical rotor tip speed in MPH * 100.
874  int rotor_velocity = 45600;
875  // Non-vehicle collisions can't happen when the vehicle is not moving
876  int &coll_velocity = ( parts[part].info().has_flag( VPFLAG_ROTOR ) == 0 ) ?
877  ( vert_coll ? vertical_velocity : velocity ) :
878  rotor_velocity;
879  if( !just_detect && coll_velocity == 0 ) {
880  return ret;
881  }
882 
883  if( is_body_collision ) {
884  // critters on a BOARDABLE part in this vehicle aren't colliding
885  if( ovp && ( &ovp->vehicle() == this ) && get_monster( ovp->part_index() ) ) {
886  return ret;
887  }
888  // we just ran into a fish, so move it out of the way
889  if( here.has_flag( ter_furn_flag::TFLAG_SWIMMABLE, critter->pos() ) ) {
890  tripoint end_pos = critter->pos();
891  tripoint start_pos;
892  const units::angle angle =
893  move.dir() + 45_degrees * ( parts[part].mount.x > pivot_point().x ? -1 : 1 );
894  const std::set<tripoint> &cur_points = get_points( true );
895  // push the animal out of way until it's no longer in our vehicle and not in
896  // anyone else's position
897  while( get_creature_tracker().creature_at( end_pos, true ) ||
898  cur_points.find( end_pos ) != cur_points.end() ) {
899  start_pos = end_pos;
900  calc_ray_end( angle, 2, start_pos, end_pos );
901  }
902  critter->setpos( end_pos );
903  return ret;
904  }
905  }
906 
907  // Damage armor before damaging any other parts
908  // Actually target, not just damage - spiked plating will "hit back", for example
909  const int armor_part = part_with_feature( ret.part, VPFLAG_ARMOR, true );
910  if( armor_part >= 0 ) {
911  ret.part = armor_part;
912  }
913  vehicle_part &vp = this->part( ret.part );
914  const vpart_info &vpi = vp.info();
915  // Let's calculate type of collision & mass of object we hit
916  float mass2 = 0.0f;
917  // e = 0 -> plastic collision
918  float e = 0.3f;
919  // e = 1 -> inelastic collision
920  //part density
921  float part_dens = 0.0f;
922 
923  if( is_body_collision ) {
924  // Check any monster/NPC/player on the way
925  // body
926  ret.type = veh_coll_body;
927  ret.target = critter;
928  e = 0.30f;
929  part_dens = 15;
930  mass2 = units::to_kilogram( critter->get_weight() );
931  ret.target_name = critter->disp_name();
932  } else if( ( bash_floor && here.is_bashable_ter_furn( p, true ) ) ||
933  ( here.is_bashable_ter_furn( p, false ) && here.move_cost_ter_furn( p ) != 2 &&
934  // Don't collide with tiny things, like flowers, unless we have a wheel in our space.
935  ( part_with_feature( ret.part, VPFLAG_WHEEL, true ) >= 0 ||
937  // Protrusions don't collide with short terrain.
938  // Tiny also doesn't, but it's already excluded unless there's a wheel present.
939  !( part_with_feature( vp.mount, "PROTRUSION", true ) >= 0 &&
941  // These are bashable, but don't interact with vehicles.
943  // Do not collide with track tiles if we can use rails
944  !( here.has_flag_ter_or_furn( ter_furn_flag::TFLAG_RAIL, p ) && this->can_use_rails() ) ) ) {
945  // Movecost 2 indicates flat terrain like a floor, no collision there.
946  ret.type = veh_coll_bashable;
947  terrain_collision_data( p, bash_floor, mass2, part_dens, e );
948  ret.target_name = here.disp_name( p );
949  } else if( here.impassable_ter_furn( p ) ||
950  ( bash_floor && !here.has_flag( ter_furn_flag::TFLAG_NO_FLOOR, p ) ) ) {
951  // not destructible
952  ret.type = veh_coll_other;
953  mass2 = 1000;
954  e = 0.10f;
955  part_dens = 80;
956  ret.target_name = here.disp_name( p );
957  }
958 
959  if( ret.type == veh_coll_nothing || just_detect ) {
960  // Hit nothing or we aren't actually hitting
961  return ret;
962  }
964  // Calculate mass AFTER checking for collision
965  // because it involves iterating over all cargo
966  // Rotors only use rotor mass in calculation.
967  const float mass = vpi.has_flag( VPFLAG_ROTOR )
968  ? to_kilogram( vp.base.weight() )
969  : to_kilogram( total_mass() );
970 
971  //Calculate damage resulting from d_E
972  const itype *type = item::find_type( vpi.base_item );
973  const auto &mats = type->materials;
974  float mat_total = type->mat_portion_total == 0 ? 1 : type->mat_portion_total;
975  float vpart_dens = 0.0f;
976  if( !mats.empty() ) {
977  for( const std::pair<const material_id, int> &mat_id : mats ) {
978  vpart_dens += mat_id.first->density() * ( static_cast<float>( mat_id.second ) / mat_total );
979  }
980  // average
981  vpart_dens /= mats.size();
982  }
983 
984  //k=100 -> 100% damage on part
985  //k=0 -> 100% damage on obj
986  float material_factor = ( part_dens - vpart_dens ) * 0.5f;
987  material_factor = std::max( -25.0f, std::min( 25.0f, material_factor ) );
988  // factor = -25 if mass is much greater than mass2
989  // factor = +25 if mass2 is much greater than mass
990  const float weight_factor = mass >= mass2 ?
991  -25 * ( std::log( mass ) - std::log( mass2 ) ) / std::log( mass ) :
992  25 * ( std::log( mass2 ) - std::log( mass ) ) / std::log( mass2 );
993 
994  float k = 50 + material_factor + weight_factor;
995  k = std::max( 10.0f, std::min( 90.0f, k ) );
996 
997  bool smashed = true;
998  const std::string snd = _( "smash!" );
999  float dmg = 0.0f;
1000  float part_dmg = 0.0f;
1001  // Calculate Impulse of car
1002  time_duration time_stunned = 0_turns;
1003 
1004  const int prev_velocity = coll_velocity;
1005  const int vel_sign = sgn( coll_velocity );
1006  // Velocity of the object we're hitting
1007  // Assuming it starts at 0, but we'll probably hit it many times
1008  // in one collision, so accumulate the velocity gain from each hit.
1009  float vel2 = 0.0f;
1010  do {
1011  smashed = false;
1012  // Impulse of vehicle
1013  const float vel1 = coll_velocity / 100.0f;
1014  // Velocity of car after collision
1015  const float vel1_a = ( mass * vel1 + mass2 * vel2 + e * mass2 * ( vel2 - vel1 ) ) /
1016  ( mass + mass2 );
1017  // Velocity of object after collision
1018  const float vel2_a = ( mass * vel1 + mass2 * vel2 + e * mass * ( vel1 - vel2 ) ) / ( mass + mass2 );
1019  // Lost energy at collision -> deformation energy -> damage
1020  const float E_before = 0.5f * ( mass * vel1 * vel1 ) + 0.5f * ( mass2 * vel2 * vel2 );
1021  const float E_after = 0.5f * ( mass * vel1_a * vel1_a ) + 0.5f * ( mass2 * vel2_a * vel2_a );
1022  const float d_E = E_before - E_after;
1023  if( d_E <= 0 ) {
1024  // Deformation energy is signed
1025  // If it's negative, it means something went wrong
1026  // But it still does happen sometimes...
1027  if( std::fabs( vel1_a ) < std::fabs( vel1 ) ) {
1028  // Lower vehicle's speed to prevent infinite loops
1029  coll_velocity = vel1_a * 90;
1030  }
1031  if( std::fabs( vel2_a ) > std::fabs( vel2 ) ) {
1032  vel2 = vel2_a;
1033  }
1034  // this causes infinite loop
1035  if( mass2 == 0 ) {
1036  mass2 = 1;
1037  }
1038  continue;
1039  }
1040 
1041  add_msg_debug( debugmode::DF_VEHICLE_MOVE, "Deformation energy: %.2f", d_E );
1042  // Damage calculation
1043  // Damage dealt overall
1044  dmg += d_E / 400;
1045  // Damage for vehicle-part
1046  // Always if no critters, otherwise if critter is real
1047  if( critter == nullptr || !critter->is_hallucination() ) {
1048  part_dmg = dmg * k / 100.0f;
1049  add_msg_debug( debugmode::DF_VEHICLE_MOVE, "Part collision damage: %.2f", part_dmg );
1050  }
1051  // Damage for object
1052  const float obj_dmg = dmg * ( 100.0f - k ) / 100.0f;
1053 
1054  if( ret.type == veh_coll_bashable ) {
1055  // Something bashable -- use map::bash to determine outcome
1056  // NOTE: Floor bashing disabled for balance reasons
1057  // Floor values are still used to set damage dealt to vehicle
1058  smashed = here.is_bashable_ter_furn( p, false ) &&
1059  here.bash_resistance( p, bash_floor ) <= obj_dmg &&
1060  here.bash( p, obj_dmg, false, false, false, this ).success;
1061  if( smashed ) {
1062  if( here.is_bashable_ter_furn( p, bash_floor ) ) {
1063  // There's new terrain there to smash
1064  smashed = false;
1065  terrain_collision_data( p, bash_floor, mass2, part_dens, e );
1066  ret.target_name = here.disp_name( p );
1067  } else if( here.impassable_ter_furn( p ) ) {
1068  // There's new terrain there, but we can't smash it!
1069  smashed = false;
1070  ret.type = veh_coll_other;
1071  mass2 = 1000;
1072  e = 0.10f;
1073  part_dens = 80;
1074  ret.target_name = here.disp_name( p );
1075  }
1076  }
1077  } else if( ret.type == veh_coll_body ) {
1078  int dam = obj_dmg * vpi.dmg_mod / 100;
1079 
1080  // We know critter is set for this type. Assert to inform static
1081  // analysis.
1082  cata_assert( critter );
1083 
1084  // No blood from hallucinations
1085  if( !critter->is_hallucination() ) {
1086  if( vpi.has_flag( "SHARP" ) ) {
1087  vp.blood += 100 + 5 * dam;
1088  } else if( dam > rng( 10, 30 ) ) {
1089  vp.blood += 50 + dam / 2 * 5;
1090  }
1091 
1093  }
1094 
1095  time_stunned = time_duration::from_turns( ( rng( 0, dam ) > 10 ) + ( rng( 0, dam ) > 40 ) );
1096  if( time_stunned > 0_turns ) {
1097  critter->add_effect( effect_stunned, time_stunned );
1098  }
1099 
1100  if( ph != nullptr ) {
1101  ph->hitall( dam, 40, driver );
1102  } else {
1103  const int armor = vpi.has_flag( "SHARP" ) ?
1104  critter->get_armor_type( damage_cut, bodypart_id( "torso" ) ) :
1105  critter->get_armor_type( damage_bash, bodypart_id( "torso" ) );
1106  dam = std::max( 0, dam - armor );
1107  critter->apply_damage( driver, bodypart_id( "torso" ), dam );
1108  if( vpi.has_flag( "SHARP" ) ) {
1109  critter->add_effect( effect_source( driver ), effect_bleed, 1_minutes * rng( 1, dam ),
1111  } else if( dam > 18 && rng( 1, 20 ) > 15 ) {
1112  //low chance of lighter bleed even with non sharp objects.
1113  critter->add_effect( effect_source( driver ), effect_bleed, 1_minutes,
1115  }
1116  add_msg_debug( debugmode::DF_VEHICLE_MOVE, "Critter collision damage: %d", dam );
1117  }
1118 
1119  // Don't fling if vertical - critter got smashed into the ground
1120  if( !vert_coll ) {
1121  if( std::fabs( vel2_a ) > 10.0f ||
1122  std::fabs( e * mass * vel1_a ) > std::fabs( mass2 * ( 10.0f - vel2_a ) ) ) {
1123  const units::angle angle = rng_float( -60_degrees, 60_degrees );
1124  // Also handle the weird case when we don't have enough force
1125  // but still have to push (in such case compare momentum)
1126  const float push_force = std::max<float>( std::fabs( vel2_a ), 10.1f );
1127  // move.dir is where the vehicle is facing. If velocity is negative,
1128  // we're moving backwards and have to adjust the angle accordingly.
1129  const units::angle angle_sum =
1130  angle + move.dir() + ( vel2_a > 0 ? 0_degrees : 180_degrees );
1131  g->fling_creature( critter, angle_sum, push_force );
1132  } else if( std::fabs( vel2_a ) > std::fabs( vel2 ) ) {
1133  vel2 = vel2_a;
1134  } else {
1135  // Vehicle's momentum isn't big enough to push the critter
1136  velocity = 0;
1137  break;
1138  }
1139 
1140  if( critter->is_dead_state() ) {
1141  smashed = true;
1142  } else if( critter != nullptr ) {
1143  // Only count critter as pushed away if it actually changed position
1144  smashed = critter->pos() != p;
1145  }
1146  }
1147  }
1148 
1149  if( critter == nullptr || !critter->is_hallucination() ) {
1150  coll_velocity = vel1_a * 100;
1151  }
1152  // Stop processing when sign inverts, not when we reach 0
1153  } while( !smashed && sgn( coll_velocity ) == vel_sign );
1154 
1155  // Apply special effects from collision.
1156  if( critter != nullptr ) {
1157  if( !critter->is_hallucination() ) {
1158  if( pl_ctrl ) {
1159  if( time_stunned > 0_turns ) {
1160  //~ 1$s - vehicle name, 2$s - part name, 3$s - NPC or monster
1161  add_msg( m_warning, _( "Your %1$s's %2$s rams into %3$s and stuns it!" ),
1162  name, vp.name(), ret.target_name );
1163  } else {
1164  //~ 1$s - vehicle name, 2$s - part name, 3$s - NPC or monster
1165  add_msg( m_warning, _( "Your %1$s's %2$s rams into %3$s!" ),
1166  name, vp.name(), ret.target_name );
1167  }
1168  }
1169 
1170  if( vpi.has_flag( "SHARP" ) ) {
1171  critter->bleed();
1172  } else {
1173  sounds::sound( p, 20, sounds::sound_t::combat, snd, false, "smash_success", "hit_vehicle" );
1174  }
1175  }
1176  } else {
1177  if( pl_ctrl ) {
1178  if( !snd.empty() ) {
1179  //~ 1$s - vehicle name, 2$s - part name, 3$s - collision object name, 4$s - sound message
1180  add_msg( m_warning, _( "Your %1$s's %2$s rams into %3$s with a %4$s" ),
1181  name, vp.name(), ret.target_name, snd );
1182  } else {
1183  //~ 1$s - vehicle name, 2$s - part name, 3$s - collision object name
1184  add_msg( m_warning, _( "Your %1$s's %2$s rams into %3$s." ),
1185  name, vp.name(), ret.target_name );
1186  }
1187  }
1188 
1189  sounds::sound( p, smashed ? 80 : 50, sounds::sound_t::combat, snd, false, "smash_success",
1190  "hit_vehicle" );
1191  }
1192 
1193  if( smashed && !vert_coll ) {
1194  int turn_amount = rng( 1, 3 ) * std::sqrt( static_cast<double>( part_dmg ) );
1195  turn_amount /= 15;
1196  if( turn_amount < 1 ) {
1197  turn_amount = 1;
1198  }
1199  turn_amount *= 15;
1200  if( turn_amount > 120 ) {
1201  turn_amount = 120;
1202  }
1203  int turn_roll = rng( 0, 100 );
1204  // Probability of skidding increases with higher delta_v
1205  if( turn_roll < std::abs( ( prev_velocity - coll_velocity ) / 100.0f * 2.0f ) ) {
1206  //delta_v = vel1 - vel1_a
1207  //delta_v = 50 mph -> 100% probability of skidding
1208  //delta_v = 25 mph -> 50% probability of skidding
1209  skidding = true;
1210  turn( units::from_degrees( one_in( 2 ) ? turn_amount : -turn_amount ) );
1211  }
1212  }
1213 
1214  ret.imp = part_dmg;
1215  return ret;
1216 }
int_id< body_part_type > bodypart_id
Definition: bodypart.h:32
#define cata_assert(expression)
Definition: cata_assert.h:36
int hitall(int dam, int vary, Creature *source)
Harms all body parts for dam, with armor reduction.
Definition: character.cpp:8454
virtual void apply_damage(Creature *source, bodypart_id bp, int amount, bool bypass_med=false)=0
virtual void bleed() const
Adds an appropriate blood splatter.
Definition: creature.cpp:230
virtual units::mass get_weight() const =0
virtual bool is_hallucination() const =0
void add_effect(const effect &eff, bool force=false, bool deferred=false)
Definition: creature.h:604
bodypart_id get_random_body_part_of_type(body_part_type::type part_type) const
Definition: creature.cpp:2686
virtual bool is_dead_state() const =0
void setpos(const tripoint &p)
Definition: creature.cpp:188
virtual int get_armor_type(const damage_type_id &dt, bodypart_id bp) const =0
shared_ptr_fast< monster > find(const tripoint_abs_ms &pos) const
Returns the monster at the given location.
units::mass weight(bool include_contents=true, bool integral=false) const
Total weight of an item accounting for all contained/integrated items.
Definition: item.cpp:7081
bool is_bashable_ter_furn(const tripoint &p, bool allow_floor=false) const
Returns true if the furniture or terrain at p is bashable.
Definition: map.cpp:3271
std::string disp_name(const tripoint &p)
Definition: map.cpp:1694
bash_params bash(const tripoint &p, int str, bool silent=false, bool destroy=false, bool bash_floor=false, const vehicle *bashing_vehicle=nullptr)
Returns a pair where first is whether anything was smashed and second is if it was destroyed.
Definition: map.cpp:4292
int move_cost_ter_furn(const tripoint &p) const
Similar behavior to move_cost(), but ignores vehicles.
Definition: map.cpp:2482
int bash_resistance(const tripoint &p, bool allow_floor=false) const
Returns min_str of the furniture or terrain at p.
Definition: map.cpp:3290
static constexpr time_duration from_turns(const T t)
Named constructors to get a duration representing a multiple of the named time units.
Definition: calendar.h:221
const point & pivot_point() const
Definition: vehicle.cpp:6547
int dmg_mod
Damage modifier (percentage) used when damaging other entities upon collision.
Definition: veh_type.h:412
void calc_ray_end(units::angle angle, const int range, const tripoint &p, tripoint &out)
Definition: line.cpp:910
double log(std::vector< double > const &params)
double rng_float(double lo, double hi)
Definition: rng.cpp:27
bool success
Definition: map.h:155
@ veh_coll_body
Definition: vehicle.h:113
@ veh_coll_bashable
Definition: vehicle.h:115
@ veh_coll_veh
Definition: vehicle.h:114
static const efftype_id effect_bleed("bleed")
static const damage_type_id damage_bash("bash")
static void terrain_collision_data(const tripoint &p, bool bash_floor, float &mass, float &density, float &elastic)
static const efftype_id effect_stunned("stunned")
static const damage_type_id damage_cut("cut")

References _, abs(), Creature::add_effect(), add_msg(), add_msg_debug, Creature::apply_damage(), vehicle_part::base, vpart_info::base_item, map::bash(), map::bash_resistance(), Creature::bleed(), vehicle_part::blood, calc_ray_end(), cata_assert, check_environmental_effects, sounds::combat, creature_tracker::creature_at(), damage_bash, damage_cut, debugmode::DF_VEHICLE_MOVE, tileray::dir(), Creature::disp_name(), map::disp_name(), vpart_info::dmg_mod, effect_bleed, effect_stunned, units::fabs(), creature_tracker::find(), item::find_type(), units::from_degrees(), time_duration::from_turns(), g, Creature::get_armor_type(), get_creature_tracker(), get_map(), get_monster(), get_player_character(), get_points(), Creature::get_random_body_part_of_type(), Creature::get_weight(), vpart_info::has_flag(), map::has_flag(), map::has_flag_ter_or_furn(), Character::hitall(), map::impassable_ter_furn(), Character::in_vehicle, vehicle_part::info(), map::is_bashable_ter_furn(), Creature::is_dead_state(), Creature::is_hallucination(), log(), m_warning, max(), min(), vehicle_part::mount, move, map::move_cost_ter_furn(), vehicle_part::name(), name, one_in(), veh_collision::part, part(), part_with_feature(), parts, pivot_point(), player_in_control(), Creature::pos(), cata::hash64_detail::ret, rng(), rng_float(), Creature::setpos(), sgn(), skidding, sm_pos, sounds::sound(), sqrt(), stop_autodriving(), bash_params::success, terrain_collision_data(), TFLAG_NO_FLOOR, TFLAG_NOCOLLIDE, TFLAG_RAIL, TFLAG_SHORT, TFLAG_SWIMMABLE, TFLAG_TINY, units::to_kilogram(), body_part_type::torso, total_mass(), turn(), type, map::veh_at(), veh_coll_bashable, veh_coll_body, veh_coll_nothing, veh_coll_other, veh_coll_veh, velocity, vertical_velocity, VPFLAG_ARMOR, VPFLAG_ROTOR, VPFLAG_WHEEL, item::weight(), point::x, and tripoint::z.

Referenced by collision().

◆ part_count()

int vehicle::part_count ( ) const

◆ part_count_real()

int vehicle::part_count_real ( ) const

Definition at line 8129 of file vehicle.cpp.

8130 {
8131  return std::count_if( parts.begin(), parts.end(),
8132  []( const vehicle_part & vp ) {
8133  return !vp.is_fake;
8134  } );
8135 }

References parts.

Referenced by veh_interact::complete_vehicle().

◆ part_count_real_cached()

int vehicle::part_count_real_cached ( ) const

Definition at line 8137 of file vehicle.cpp.

8138 {
8139  return static_cast<int>( parts.size() - fake_parts.size() );
8140 }
std::vector< int > fake_parts
Definition: vehicle.h:2197

References fake_parts, and parts.

◆ part_displayed_at()

int vehicle::part_displayed_at ( const point dp,
bool  include_fake = false,
bool  below_roof = true,
bool  roof = true 
) const

Returns which part (as an index into the parts list) is the one that will be displayed for the given square.

Returns -1 if there are no parts in that square.

Parameters
dpThe local coordinate.
below_roofInclude parts below roof.
roofInclude roof parts.
Returns
The index of the part that will be displayed.

Definition at line 3246 of file vehicle.cpp.

3248 {
3249  // Z-order is implicitly defined in game::load_vehiclepart, but as
3250  // numbers directly set on parts rather than constants that can be
3251  // used elsewhere. A future refactor might be nice but this way
3252  // it's clear where the magic number comes from.
3253  const int ON_ROOF_Z = 9;
3254 
3255  std::vector<int> parts_in_square = parts_at_relative( dp, true, include_fake );
3256 
3257  if( parts_in_square.empty() ) {
3258  return -1;
3259  }
3260 
3261  bool in_vehicle = !roof;
3262 
3263  if( roof ) {
3264  in_vehicle = is_passenger( get_player_character() );
3265  }
3266 
3267  int hide_z_at_or_above = in_vehicle ? ON_ROOF_Z : INT_MAX;
3268 
3269  int top_part = -1;
3270  int top_z_order = ( below_roof ? 0 : ON_ROOF_Z ) - 1;
3271  for( size_t index = 0; index < parts_in_square.size(); index++ ) {
3272  int test_index = parts_in_square[index];
3273  const vehicle_part &vp = parts.at( test_index );
3274  if( !vp.is_real_or_active_fake() ) {
3275  continue;
3276  }
3277  int test_z_order = vp.info().z_order;
3278  if( ( top_z_order < test_z_order ) && ( test_z_order < hide_z_at_or_above ) ) {
3279  top_part = index;
3280  top_z_order = test_z_order;
3281  }
3282  }
3283  if( top_part < 0 ) {
3284  return top_part;
3285  }
3286 
3287  return parts_in_square[top_part];
3288 }
int z_order
Definition: veh_type.h:456

References get_player_character(), vehicle_part::info(), is_passenger(), vehicle_part::is_real_or_active_fake(), parts, parts_at_relative(), and vpart_info::z_order.

Referenced by map::add_splatter(), get_display_of_tile(), veh_interact::part_at(), vpart_position::part_displayed(), vehicle_prototype::save_vehicle_as_prototype(), and separate_from_grid().

◆ part_epower()

units::power vehicle::part_epower ( const vehicle_part vp) const
private

Definition at line 1137 of file vehicle.cpp.

1138 {
1139  units::power e = vp.info().epower;
1140  if( e < 0_W ) {
1141  return e; // Consumers always draw full power, even if broken
1142  }
1143  return e * vp.health_percent();
1144 }

References vpart_info::epower, vehicle_part::health_percent(), and vehicle_part::info().

Referenced by active_reactor_epower(), basic_consumption(), max_reactor_epower(), power_parts(), start_engine(), total_alternator_epower(), total_engine_epower(), total_solar_epower(), total_water_wheel_epower(), total_wind_epower(), and update_time().

◆ part_has_lock()

bool vehicle::part_has_lock ( int  part_index) const

Definition at line 2963 of file vehicle.cpp.

2964 {
2965  for( const int elem : parts_at_relative( parts[p].mount, true, true ) ) {
2966  const vehicle_part &vp = parts[elem];
2967  if( vp.info().has_flag( "DOOR_LOCKING" ) && vp.is_available() ) {
2968  return true;
2969  }
2970  }
2971  return false;
2972 }

References vpart_info::has_flag(), vehicle_part::info(), vehicle_part::is_available(), parts, and parts_at_relative().

Referenced by next_part_to_lock(), next_part_to_open(), and next_part_to_unlock().

◆ part_removal_cleanup()

void vehicle::part_removal_cleanup ( )

Definition at line 2133 of file vehicle.cpp.

2134 {
2135  map &here = get_map();
2136  remove_fake_parts( false );
2137  const bool changed = do_remove_part_actual();
2138  if( changed || parts.empty() ) {
2139  refresh();
2140  if( parts.empty() ) {
2141  here.destroy_vehicle( this );
2142  return;
2143  } else {
2144  here.add_vehicle_to_cache( this );
2145  }
2146  }
2147  shift_if_needed( here );
2148  // If we've split away all of a power grid's parts, rename it from "power grid" to its part name.
2149  if( is_powergrid() && name == power_grid_name.translated() && part_count() == 1 ) {
2150  name = parts[0].info().name();
2151  }
2152  refresh( false ); // Rebuild cached indices
2154  coeff_air_changed = false;
2155 }
void add_vehicle_to_cache(vehicle *)
Definition: map.cpp:459
bool is_powergrid() const
Definition: vehicle.cpp:1952
bool do_remove_part_actual()
Definition: vehicle.cpp:2105

References map::add_vehicle_to_cache(), coeff_air_changed, coeff_air_dirty, map::destroy_vehicle(), do_remove_part_actual(), get_map(), is_powergrid(), name, part_count(), parts, power_grid_name, refresh(), remove_fake_parts(), shift_if_needed(), and translation::translated().

Referenced by veh_interact::complete_vehicle(), link_up_actor::link_to_veh_app(), place_appliance(), remove_carried_vehicle(), veh_utils::repair_part(), and separate_from_grid().

◆ part_to_item()

item vehicle::part_to_item ( const vehicle_part vp) const

Generate the corresponding item from this vehicle part.

It includes the hp (item damage), fuel charges (battery or liquids), aspect, ...

Definition at line 8223 of file vehicle.cpp.

8224 {
8225  item tmp = vp.base;
8226  tmp.unset_flag( flag_VEHICLE );
8227 
8228  // Cables get special handling: their target coordinates need to remain
8229  // stored, and if a cable actually drops, it should be half-connected.
8230  // Tow cables are handled inside of invalidate_towing instead.
8231  if( tmp.has_flag( flag_CABLE_SPOOL ) && !tmp.has_flag( flag_TOW_CABLE ) ) {
8232  tmp.reset_link( false );
8233  const std::optional<vpart_reference> remote = get_remote_part( vp );
8234  if( remote &&
8235  tmp.link_to( remote->vehicle(), remote->part().mount, link_state::automatic ).success() ) {
8236  tmp.link().t_abs_pos = tripoint_abs_ms( vp.target.second );
8237  } else {
8238  // The linked vehicle can't be found, so this part shouldn't exist.
8239  tmp.set_flag( flag_NO_DROP );
8240  }
8241  }
8242 
8243  // quantize damage and degradation to the middle of each damage_level so that items will stack nicely
8244  tmp.set_damage( ( tmp.damage_level() - 0.5 ) * itype::damage_scale );
8245  tmp.set_degradation( ( tmp.damage_level() - 0.5 ) * itype::damage_scale );
8246  return tmp;
8247 }
item & set_flag(const flag_id &flag)
Idempotent filter setting an item specific flag.
Definition: item.cpp:7602
void set_degradation(int qty)
Sets item's degradation constrained by [0 and max_damage] If item damage is lower it is raised up to ...
Definition: item.cpp:910
int damage_level(bool precise=false) const
Definition: item.cpp:876
item & unset_flag(const flag_id &flag)
Idempotent filter removing an item specific flag.
Definition: item.cpp:7641
std::optional< vpart_reference > get_remote_part(const vehicle_part &vp_local) const
Get the remote vehicle and part that a part is targeting.
Definition: vehicle.cpp:6950
const flag_id flag_VEHICLE("VEHICLE")
const flag_id flag_CABLE_SPOOL("CABLE_SPOOL")
const flag_id flag_TOW_CABLE("TOW_CABLE")
static constexpr int damage_scale
Definition: itype.h:1465

References automatic, vehicle_part::base, item::damage_level(), itype::damage_scale, flag_CABLE_SPOOL, flag_NO_DROP, flag_TOW_CABLE, flag_VEHICLE, get_remote_part(), item::has_flag(), item::link(), item::link_to(), item::reset_link(), item::set_damage(), item::set_degradation(), item::set_flag(), ret_val_common::success(), item::link_data::t_abs_pos, vehicle_part::target, and item::unset_flag().

Referenced by break_off(), veh_interact::can_remove_part(), veh_interact::complete_vehicle(), damage_direct(), invalidate_towing(), merge_vehicle_parts(), remove_part(), removed_part(), shed_loose_parts(), and unlink_cables().

◆ part_vpower_w()

units::power vehicle::part_vpower_w ( const vehicle_part vp,
bool  at_full_hp = false 
) const
private
Strength increases power produced for MUSCLE_* vehicles

wind-powered vehicles have differing power depending on wind direction

Definition at line 1077 of file vehicle.cpp.

1078 {
1079  const vpart_info &vpi = vp.info();
1080  const int vp_index = index_of_part( &vp );
1081  units::power pwr = vpi.power;
1082  if( vpi.has_flag( VPFLAG_ENGINE ) ) {
1083  if( vpi.fuel_type == fuel_type_animal ) {
1084  int factor = 0;
1085  if( const monster *mon = get_monster( vp_index ); mon && mon->has_effect( effect_harnessed ) ) {
1086  factor += mon->get_size() - 1;
1087  factor *= mon->get_speed();
1088  factor *= mon->get_mountable_weight_ratio();
1089  }
1090  pwr = 15_W * factor;
1091  } else if( vpi.fuel_type == fuel_type_muscle ) {
1092  if( const Character *muscle_user = get_passenger( vp_index ) ) {
1093  // Calculate virtual strength bonus from cycling proficiency
1094  float muscle_veh_boost_bonus = 0;
1095  const float athlete_form_bonus = muscle_user->get_proficiency_bonus( "athlete",
1097  if( muscle_user->has_trait_flag( json_flag_MUSCLE_VEH_BOOST ) ) {
1098  muscle_veh_boost_bonus = 8;
1099  }
1100  ///\EFFECT_STR increases power produced for MUSCLE_* vehicles
1101  const float muscle_multiplier = muscle_user->str_cur - 8 + athlete_form_bonus +
1102  muscle_veh_boost_bonus;
1103  const float weary_multiplier = muscle_user->exertion_adjusted_move_multiplier();
1104  const float engine_multiplier = vpi.engine_info->muscle_power_factor;
1105  pwr += units::from_watt( muscle_multiplier * weary_multiplier * engine_multiplier );
1106  }
1107  } else if( vpi.fuel_type == fuel_type_wind ) {
1108  /// wind-powered vehicles have differing power depending on wind direction
1109  const weather_manager &weather = get_weather();
1110  const double raddir = ( ( weather.winddirection + 180 ) % 360 ) * ( M_PI / 180 );
1111  const rl_vec2d windvec( std::sin( raddir ), -std::cos( raddir ) );
1112  const double dot = windvec.dot_product( face_vec() );
1113  const units::power windeffectint = units::from_watt( weather.windspeed * dot * 200 );
1114  pwr = std::max( 1_W, pwr + windeffectint );
1115  }
1116  }
1117 
1118  if( pwr < 0_W ) {
1119  return pwr; // Consumers always draw full power, even if broken
1120  }
1121  if( at_full_hp ) {
1122  return pwr; // Assume full hp
1123  }
1124  // Damaged engines give less power, but some engines handle it better
1125  // dpf is 0 for engines that scale power linearly with damage and
1126  // provides a floor otherwise
1127  if( vpi.has_flag( VPFLAG_ENGINE ) ) {
1128  const float dpf = vpi.engine_info->damaged_power_factor;
1129  pwr *= dpf + ( ( 1.0f - dpf ) * vp.health_percent() );
1130  }
1131  return pwr;
1132 }
units::power power
For engines and motors this is maximum output (watts) For alternators is engine power consumed (negat...
Definition: veh_type.h:430
double sin(std::vector< double > const &params)
double cos(std::vector< double > const &params)
constexpr quantity< value_type, power_in_milliwatt_tag > from_watt(const value_type v)
Definition: units.h:599
static const json_character_flag json_flag_MUSCLE_VEH_BOOST("MUSCLE_VEH_BOOST")

References cos(), dot(), rl_vec2d::dot_product(), effect_harnessed, vpart_info::engine_info, face_vec(), units::from_watt(), vpart_info::fuel_type, fuel_type_animal, fuel_type_muscle, fuel_type_wind, get_monster(), get_passenger(), get_weather(), Creature::has_effect(), vpart_info::has_flag(), vehicle_part::health_percent(), index_of_part(), vehicle_part::info(), json_flag_MUSCLE_VEH_BOOST, M_PI, max(), vpart_info::power, sin(), strength, and VPFLAG_ENGINE.

Referenced by backfire(), basic_consumption(), engine_start_time(), noise_and_smoke(), total_power(), and update_alternator_load().

◆ part_with_feature() [1/3]

int vehicle::part_with_feature ( const point pt,
const std::string &  f,
bool  unbroken 
) const

Returns index of part at mount point pt which has given f flag.

Note
does not use relative_parts cache
Parameters
ptonly returns parts from this mount point
frequired flag in part's vpart_info flags collection
unbrokenif true also requires the part to be !is_broken
Returns
part index or -1

Definition at line 2785 of file vehicle.cpp.

2786 {
2787  for( const int p : parts_at_relative( pt, /* use_cache = */ false ) ) {
2788  const vehicle_part &vp_here = this->part( p );
2789  if( vp_here.info().has_flag( flag ) && !( unbroken && vp_here.is_broken() ) ) {
2790  return p;
2791  }
2792  }
2793  return -1;
2794 }

References vpart_info::has_flag(), vehicle_part::info(), vehicle_part::is_broken(), part(), and parts_at_relative().

Referenced by act_on_map(), avail_part_with_feature(), damage(), damage_all(), get_display_of_tile(), get_monster(), get_passenger(), part_collision(), vpart_position::part_with_feature(), place_spawn_items(), player_in_control(), pldrive(), process_vehicle_items(), refresh(), refresh_insides(), refresh_pivot(), refresh_zones(), remove_part(), map::shake_vehicle(), smash_security_system(), vehicle_caching_internal(), and map::vehicle_vehicle_collision().

◆ part_with_feature() [2/3]

int vehicle::part_with_feature ( const point pt,
vpart_bitflags  f,
bool  unbroken 
) const

Returns part index at mount point pt which has given f flag.

Note
uses relative_parts cache
Parameters
ptonly returns parts from this mount point
frequired flag in part's vpart_info flags collection
unbrokenif true also requires the part to be !is_broken()
Returns
part index or -1

Definition at line 2774 of file vehicle.cpp.

2775 {
2776  for( const int p : parts_at_relative( pt, /* use_cache = */ true ) ) {
2777  const vehicle_part &vp_here = this->part( p );
2778  if( vp_here.info().has_flag( f ) && !( unbroken && vp_here.is_broken() ) ) {
2779  return p;
2780  }
2781  }
2782  return -1;
2783 }

References vpart_info::has_flag(), vehicle_part::info(), vehicle_part::is_broken(), part(), and parts_at_relative().

◆ part_with_feature() [3/3]

int vehicle::part_with_feature ( int  p,
vpart_bitflags  f,
bool  unbroken 
) const

Returns p or part index at mount point pt which has given f flag.

Note
uses relative_parts cache
Parameters
pindex of part to start searching from
frequired flag in part's vpart_info flags collection
unbrokenif true also requires the part to be !is_broken()
Returns
part index or -1

Definition at line 2759 of file vehicle.cpp.

2760 {
2761  const vehicle_part &vp = this->part( part );
2762  if( vp.info().has_flag( flag ) && !( unbroken && vp.is_broken() ) ) {
2763  return part;
2764  }
2765  for( const int p : parts_at_relative( vp.mount, /* use_cache = */ true ) ) {
2766  const vehicle_part &vp_here = this->part( p );
2767  if( vp_here.info().has_flag( flag ) && !( unbroken && vp_here.is_broken() ) ) {
2768  return p;
2769  }
2770  }
2771  return -1;
2772 }

References vpart_info::has_flag(), vehicle_part::info(), vehicle_part::is_broken(), vehicle_part::mount, part(), and parts_at_relative().

◆ parts_at_relative()

std::vector< int > vehicle::parts_at_relative ( const point dp,
bool  use_cache,
bool  include_fake = false 
) const

Definition at line 2569 of file vehicle.cpp.

2571 {
2572  std::vector<int> res;
2573  if( !use_cache ) {
2574  if( include_fake ) {
2575  for( const vpart_reference &vp : get_all_parts_with_fakes() ) {
2576  if( vp.mount() == dp && !vp.part().removed ) {
2577  res.push_back( static_cast<int>( vp.part_index() ) );
2578  }
2579  }
2580  } else {
2581  for( const vpart_reference &vp : get_all_parts() ) {
2582  if( vp.mount() == dp && !vp.part().removed ) {
2583  res.push_back( static_cast<int>( vp.part_index() ) );
2584  }
2585  }
2586  }
2587  } else {
2588  const auto &iter = relative_parts.find( dp );
2589  if( iter != relative_parts.end() ) {
2590  if( include_fake ) {
2591  return iter->second;
2592  } else {
2593  for( const int vp : iter->second ) {
2594  if( !parts.at( vp ).is_fake ) {
2595  res.push_back( vp );
2596  }
2597  }
2598  }
2599  }
2600  }
2601  return res;
2602 }
vehicle_part_with_fakes_range get_all_parts_with_fakes(bool with_inactive=false) const
Definition: vehicle.cpp:8218

References get_all_parts(), get_all_parts_with_fakes(), parts, and relative_parts.

Referenced by avail_linkable_part(), break_off(), veh_app_interact::can_disconnect(), can_mount(), can_unmount(), coeff_air_drag(), veh_interact::complete_vehicle(), damage(), MapExtras::delete_items_at_mount(), optional_vpart_position::extended_description(), find_and_split_vehicles(), find_vehicles_to_unrack(), has_quality_from_vpart(), has_structural_part(), is_connected(), max_quality_from_vpart(), merge_rackable_vehicle(), map::mop_spills(), veh_interact::move_cursor(), next_part_to_close(), next_part_to_lock(), next_part_to_open(), next_part_to_unlock(), open_all_at(), part_displayed_at(), part_has_lock(), part_with_feature(), print_part_list(), print_vparts_descs(), refresh_insides(), remove_carried_vehicle(), remove_part(), DefaultRemovePartHandler::removed(), roof_at_part(), shift_if_needed(), smash(), map::terrain_moppable(), and unlink_cables().

◆ pivot_displacement()

point vehicle::pivot_displacement ( ) const

Definition at line 3501 of file vehicle.cpp.

3502 {
3503  // precalc_mounts always produces a result that puts the pivot point at (0,0).
3504  // If the pivot point changes, this artificially moves the vehicle, as the position
3505  // of the old pivot point will appear to move from (posx+0, posy+0) to some other point
3506  // (posx+dx,posy+dy) even if there is no change in vehicle position or rotation.
3507  // This method finds that movement so it can be canceled out when actually moving
3508  // the vehicle.
3509 
3510  // rotate the old pivot point around the new pivot point with the old rotation angle
3511  tripoint dp;
3513  return dp.xy();
3514 }

References coord_translate(), pivot_anchor, pivot_rotation, and tripoint::xy().

Referenced by game::grabbed_veh_move(), and map::move_vehicle().

◆ pivot_point()

const point & vehicle::pivot_point ( ) const

Definition at line 6547 of file vehicle.cpp.

6548 {
6549  if( pivot_dirty ) {
6550  refresh_pivot();
6551  }
6552 
6553  return pivot_cache;
6554 }
point pivot_cache
Definition: vehicle.h:2236
void refresh_pivot() const
Definition: vehicle.cpp:6556

References pivot_cache, pivot_dirty, and refresh_pivot().

Referenced by veh_interact::display_veh(), game::grabbed_veh_move(), map::move_vehicle(), part_collision(), and split_vehicles().

◆ place_spawn_items()

void vehicle::place_spawn_items ( )

Definition at line 5953 of file vehicle.cpp.

5954 {
5955  if( !type.is_valid() ) {
5956  return;
5957  }
5958 
5959  for( const vehicle_prototype::part_def &pt : type->parts ) {
5960  if( pt.with_ammo ) {
5961  int turret = part_with_feature( pt.pos, "TURRET", true );
5962  if( turret >= 0 && x_in_y( pt.with_ammo, 100 ) ) {
5963  parts[ turret ].ammo_set( random_entry( pt.ammo_types ), rng( pt.ammo_qty.first,
5964  pt.ammo_qty.second ) );
5965  }
5966  }
5967  }
5968 
5969  const float spawn_rate = get_option<float>( "ITEM_SPAWNRATE" );
5970  for( const vehicle_item_spawn &spawn : type->item_spawns ) {
5971  int part = part_with_feature( spawn.pos, "CARGO", false );
5972  if( part < 0 ) {
5973  debugmsg( "No CARGO parts at (%d, %d) of %s!", spawn.pos.x, spawn.pos.y, name );
5974  } else {
5975  vehicle_part &vp = parts[part];
5976  const bool broken = vp.is_broken();
5977 
5978  std::vector<item> created;
5979  const int spawn_count = roll_remainder( spawn.chance * std::max( spawn_rate, 1.0f ) / 100.0f );
5980  for( int i = 0; i < spawn_count; ++i ) {
5981  // if vehicle part is broken only 50% of items spawn and they will be variably damaged
5982  if( broken && one_in( 2 ) ) {
5983  continue;
5984  }
5985 
5986  for( const itype_id &e : spawn.item_ids ) {
5987  if( rng_float( 0, 1 ) < spawn_rate ) {
5988  item spawn( e );
5989  created.emplace_back( spawn.in_its_container() );
5990  }
5991  }
5992  for( const std::pair<itype_id, std::string> &e : spawn.variant_ids ) {
5993  if( rng_float( 0, 1 ) < spawn_rate ) {
5994  item spawn( e.first );
5995  item added = spawn.in_its_container();
5996  added.set_itype_variant( e.second );
5997  created.push_back( added );
5998  }
5999  }
6000  for( const item_group_id &e : spawn.item_groups ) {
6003  created.insert( created.end(), group_items.begin(), group_items.end() );
6004  }
6005  }
6006  for( item &e : created ) {
6007  if( e.is_null() ) {
6008  continue;
6009  }
6010  if( broken && e.mod_damage( rng( 1, e.max_damage() ) ) ) {
6011  continue; // we destroyed the item
6012  }
6013  if( e.is_tool() || e.is_gun() || e.is_magazine() ) {
6014  bool spawn_ammo = rng( 0, 99 ) < spawn.with_ammo && e.ammo_remaining() == 0;
6015  bool spawn_mag = rng( 0, 99 ) < spawn.with_magazine && !e.magazine_integral() &&
6016  !e.magazine_current();
6017 
6018  if( spawn_mag ) {
6019  item mag( e.magazine_default(), e.birthday() );
6020  if( spawn_ammo ) {
6021  mag.ammo_set( mag.ammo_default() );
6022  }
6023  e.put_in( mag, pocket_type::MAGAZINE_WELL );
6024  } else if( spawn_ammo && e.is_magazine() ) {
6025  e.ammo_set( e.ammo_default() );
6026  }
6027  }
6028 
6029  // Copy vehicle owner for items within
6030  if( has_owner() ) {
6031  e.set_owner( get_owner() );
6032  }
6033 
6034  add_item( vp, e );
6035  }
6036  }
6037  }
6038 }
bool x_in_y(const time_duration &a, const time_duration &b)
Definition: calendar.cpp:784
void set_itype_variant(const std::string &variant)
Set the gun variant of this item.
Definition: item.cpp:9361
time_point start_of_cataclysm
Definition: calendar.cpp:36
std::vector< item > ItemList
Definition: item_group.h:50
ItemList items_from(const item_group_id &group_id, const time_point &birthday, spawn_flags flags=spawn_flags::none)
Create items from the given group.
Definition: item_group.cpp:979
std::vector< itype_id > item_ids
Definition: veh_type.h:473
int with_magazine
Chance [0-100%] for items to spawn with their default magazine (if any)
Definition: veh_type.h:472
std::vector< std::pair< itype_id, std::string > > variant_ids
Definition: veh_type.h:475
std::vector< item_group_id > item_groups
Definition: veh_type.h:476
int with_ammo
Chance [0-100%] for items to spawn with ammo (plus default magazine if necessary)
Definition: veh_type.h:470
std::pair< int, int > ammo_qty
Definition: veh_type.h:491
std::set< itype_id > ammo_types
Definition: veh_type.h:490
std::vector< part_def > parts
Definition: veh_type.h:505
std::vector< vehicle_item_spawn > item_spawns
Definition: veh_type.h:506

References add_item(), item::ammo_default(), vehicle_prototype::part_def::ammo_qty, item::ammo_set(), vehicle_prototype::part_def::ammo_types, broken, vehicle_item_spawn::chance, debugmsg, get_owner(), has_owner(), item::in_its_container(), vehicle_part::is_broken(), string_id< T >::is_valid(), vehicle_item_spawn::item_groups, vehicle_item_spawn::item_ids, vehicle_prototype::item_spawns, item_group::items_from(), MAGAZINE_WELL, max(), name, one_in(), part(), part_with_feature(), vehicle_prototype::parts, parts, vehicle_item_spawn::pos, vehicle_prototype::part_def::pos, item::put_in(), random_entry(), rng(), rng_float(), roll_remainder(), item::set_itype_variant(), calendar::start_of_cataclysm, type, use_spawn_rate, vehicle_item_spawn::variant_ids, vehicle_item_spawn::with_ammo, vehicle_prototype::part_def::with_ammo, vehicle_item_spawn::with_magazine, point::x, x_in_y(), and point::y.

◆ place_zones()

void vehicle::place_zones ( map pmap) const

Definition at line 6040 of file vehicle.cpp.

6041 {
6042  if( !type.is_valid() || !has_owner() ) {
6043  return;
6044  }
6045  for( vehicle_prototype::zone_def const &d : type->zone_defs ) {
6046  tripoint const pt = pmap.getabs( tripoint( pos + d.pt, pmap.get_abs_sub().z() ) );
6047  mapgen_place_zone( pt, pt, d.zone_type, get_owner(), d.name, d.filter, &pmap );
6048  }
6049 }
void mapgen_place_zone(tripoint const &start, tripoint const &end, zone_type_id const &type, faction_id const &fac, std::string const &name, std::string const &filter, map *pmap)
Definition: clzones.cpp:1802
std::vector< zone_def > zone_defs
Definition: veh_type.h:507

References vehicle_prototype::zone_def::filter, map::get_abs_sub(), get_owner(), map::getabs(), has_owner(), string_id< T >::is_valid(), mapgen_place_zone(), vehicle_prototype::zone_def::name, pos, vehicle_prototype::zone_def::pt, tripoint, type, coords::coord_point_mut< Point, Subpoint, InBounds >::z(), vehicle_prototype::zone_defs, and vehicle_prototype::zone_def::zone_type.

Referenced by map::add_vehicle().

◆ play_chimes()

void vehicle::play_chimes ( ) const

Definition at line 945 of file vehicle_use.cpp.

946 {
947  if( !one_in( 3 ) ) {
948  return;
949  }
950 
951  for( const vpart_reference &vp : get_enabled_parts( "CHIMES" ) ) {
952  sounds::sound( vp.pos(), 40, sounds::sound_t::music,
953  _( "a simple melody blaring from the loudspeakers." ), false, "vehicle", "chimes" );
954  }
955 }

References _, get_enabled_parts(), sounds::music, one_in(), and sounds::sound().

Referenced by idle().

◆ play_music()

void vehicle::play_music ( ) const

Definition at line 937 of file vehicle_use.cpp.

938 {
939  Character &player_character = get_player_character();
940  for( const vpart_reference &vp : get_enabled_parts( "STEREO" ) ) {
941  iuse::play_music( &player_character, vp.pos(), 15, 30 );
942  }
943 }
void play_music(Character *p, const tripoint &source, int volume, int max_morale)
Definition: iuse.cpp:3773

References get_enabled_parts(), get_player_character(), iuse::play_music(), and Creature::pos().

Referenced by idle().

◆ player_in_control()

bool vehicle::player_in_control ( const Character p) const

Definition at line 253 of file vehicle.cpp.

254 {
255  // Debug switch to prevent vehicles from skidding
256  // without having to place the player in them.
257  if( tags.count( "IN_CONTROL_OVERRIDE" ) ) {
258  return true;
259  }
260 
261  const optional_vpart_position vp = get_map().veh_at( p.pos() );
262  if( vp && &vp->vehicle() == this &&
264  ( ( part_with_feature( vp->mount(), "CONTROL_ANIMAL", true ) >= 0 &&
266  ( part_with_feature( vp->part_index(), VPFLAG_CONTROLS, false ) >= 0 ) )
267  ) {
268  return true;
269  }
270 
271  return remote_controlled( p );
272 }
monster * get_harnessed_animal() const

References Character::controlling_vehicle, fuel_type_animal, get_harnessed_animal(), get_map(), has_engine_type(), part_with_feature(), Creature::pos(), remote_controlled(), tags, map::veh_at(), and VPFLAG_CONTROLS.

Referenced by act_on_map(), game::calc_driving_offset(), can_do_activity_there(), game::control_vehicle(), do_autodrive(), map::draw_maptile(), fuel_left(), gain_moves(), handle_trap(), idle(), talker_character_const::is_in_control_of(), is_rotorcraft(), on_move(), part_collision(), Character::pause(), Character::perform_technique(), power_parts(), map::shake_vehicle(), smart_controller_handle_turn(), and thrust().

◆ pldrive()

void vehicle::pldrive ( Character driver,
const point p,
int  z = 0 
)

Player is driving the vehicle.

Parameters
pdirection player is steering
zfor vertical movement - e.g helicopters
Dexterity reduces chance of losing control of vehicle when turning Perception reduces chance of losing control of vehicle when turning Driving reduces chance of losing control of vehicle when turning Dexterity increases chance of regaining control of a vehicle Driving increases chance of regaining control of a vehicle

Definition at line 1415 of file vehicle_move.cpp.

1416 {
1417  bool is_non_proficient = false;
1418  float effective_driver_skill = driver.get_skill_level( skill_driving );
1419  float vehicle_proficiency;
1420  // Check if you're piloting on land or water, and reduce effective driving skill proportional to relevant proficiencies (10% Boat Proficiency = 10% driving skill on water)
1422  is_non_proficient = true;
1423  vehicle_proficiency = driver.get_proficiency_practice( proficiency_prof_driver );
1424  } else if( !driver.has_proficiency( proficiency_prof_boat_pilot ) && in_deep_water ) {
1425  is_non_proficient = true;
1426  vehicle_proficiency = driver.get_proficiency_practice( proficiency_prof_boat_pilot );
1427  }
1428 
1429  bool non_prof_fumble = false;
1430  float non_prof_penalty = 0;
1431  //If you lack the appropriate piloting proficiency, increase handling penalty, and roll chance to fumble while steering
1432  if( is_non_proficient ) {
1433  effective_driver_skill *= vehicle_proficiency;
1434  non_prof_penalty = std::max( 0.0f,
1435  ( 1.0f - vehicle_proficiency ) * 10.0f -
1436  ( driver.get_dex() + driver.get_per() ) * 0.25f );
1437  non_prof_fumble = one_in( vehicle_proficiency * 12.0f +
1438  ( driver.get_dex() + driver.get_per() ) * 0.5f + 6.0f );
1439  // Penalties mitigated by proficiency progress, and dex/per stats.
1440  // - Unskilled pilot at Per/Dex 4: 1-in-8 chance to fumble while turning
1441  // - Unskilled pilot at Per/Dex 8: 1-in-10
1442  // - Unskilled pilot at Per/Dex 12: 1-in-12
1443  // - 50% Skill at Per/Dex 4: 1-in-14 chance
1444  // - 50% Skill at Per/Dex 8: 1-in-16 chance
1445  // - 50% Skill at Per/Dex 12: 1-in-18 chance
1446  }
1447  if( z != 0 && is_rotorcraft() ) {
1448  driver.set_moves( std::min( driver.get_moves(), 0 ) );
1449  thrust( 0, z );
1450  }
1451  units::angle turn_delta = vehicles::steer_increment * p.x;
1452  const float handling_diff = handling_difficulty() + non_prof_penalty;
1453  if( turn_delta != 0_degrees ) {
1454  float eff = steering_effectiveness();
1455  if( eff == -2 ) {
1456  driver.add_msg_if_player( m_info,
1457  _( "You cannot steer an animal-drawn vehicle with no animal harnessed." ) );
1458  return;
1459  }
1460 
1461  if( eff < 0 ) {
1462  driver.add_msg_if_player( m_info,
1463  _( "This vehicle has no steering system installed, you can't turn it." ) );
1464  return;
1465  }
1466 
1467  if( eff == 0 ) {
1468  driver.add_msg_if_player( m_bad, _( "The steering is completely broken!" ) );
1469  return;
1470  }
1471 
1472  // If you've got more moves than speed, it's most likely time stop
1473  // Let's get rid of that
1474  driver.set_moves( std::min( driver.get_moves(), driver.get_speed() ) );
1475 
1476  ///\EFFECT_DEX reduces chance of losing control of vehicle when turning
1477 
1478  ///\EFFECT_PER reduces chance of losing control of vehicle when turning
1479 
1480  ///\EFFECT_DRIVING reduces chance of losing control of vehicle when turning
1481  float skill = std::min( 10.0f, effective_driver_skill +
1482  ( driver.get_dex() + driver.get_per() ) / 10.0f );
1483  float penalty = rng_float( 0.0f, handling_diff ) - skill;
1484 
1485  int cost;
1486  if( penalty > 0.0f ) {
1487  // At 10 penalty (rather hard to get), we're taking 4 turns per turn
1488  cost = 100 * ( 1.0f + penalty / 2.5f );
1489  } else {
1490  // At 10 skill, with a perfect vehicle, we could turn up to 3 times per turn
1491  cost = std::max( driver.get_speed(), 100 ) * ( 1.0f - ( -penalty / 10.0f ) * 2 / 3 );
1492  }
1493 
1494  // Chance to fumble steering when in a non-proficient vehicle, or in difficult conditions
1495  if( non_prof_fumble || penalty > skill || ( penalty > 0 && cost > 400 ) ) {
1496  int fumble_roll = rng( 0, 6 );
1497  int fumble_factor = 0;
1498  int fumble_time = 1;
1499  if( fumble_roll <= 1 ) {
1500  // On a 0 or 1, fumble briefly instead of steering for 1 turn
1501  driver.add_msg_if_player( m_warning, _( "You fumble with the %s's controls." ), name );
1502  } else if( fumble_roll <= 4 ) {
1503  // On a 2, 3, or 4, steer as intended but take 2 turns to do it
1504  driver.add_msg_if_player( m_warning, _( "You turn slower than you meant to." ) );
1505  fumble_factor = 1;
1506  fumble_time = 2;
1507  } else {
1508  // On a 5 or 6, steer twice as far as you meant to, and take 2 turns to do it.
1509  driver.add_msg_if_player( m_warning, _( "You oversteer the %s!" ), name );
1510  fumble_factor = 2;
1511  fumble_time = 2;
1512  }
1513  turn_delta *= fumble_factor;
1514  cost = std::max( cost, driver.get_moves() + fumble_time * 100 );
1515  } else if( one_in( 10 ) ) {
1516  // Don't warn all the time or it gets spammy
1517  if( cost >= driver.get_speed() * 2 ) {
1518  driver.add_msg_if_player( m_warning, _( "It takes you a very long time to steer the vehicle!" ) );
1519  } else if( cost >= driver.get_speed() * 1.5f ) {
1520  driver.add_msg_if_player( m_warning, _( "It takes you a long time to steer the vehicle!" ) );
1521  }
1522  }
1523 
1524  turn( turn_delta );
1525 
1526  // At most 3 turns per turn, because otherwise it looks really weird and jumpy
1527  driver.mod_moves( -std::max( cost, driver.get_speed() / 3 + 1 ) );
1528  }
1529 
1530  if( p.y != 0 ) {
1531  cruise_thrust( -p.y * 400 );
1532  }
1533 
1534  // TODO: Actually check if we're on land on water (or disable water-skidding)
1535  if( skidding && p.x != 0 && valid_wheel_config() ) {
1536  ///\EFFECT_DEX increases chance of regaining control of a vehicle
1537 
1538  ///\EFFECT_DRIVING increases chance of regaining control of a vehicle
1539  if( handling_diff * rng( 1, 10 ) <
1540  driver.dex_cur + effective_driver_skill * 2 ) {
1541  driver.add_msg_if_player( _( "You regain control of the %s." ), name );
1542  driver.practice( skill_driving, velocity / 5 );
1543  velocity = static_cast<int>( forward_velocity() );
1544  skidding = false;
1545  move.init( turn_dir );
1546  }
1547  }
1548 }
int get_dex() const
Definition: character.cpp:4131
int dex_cur
Definition: character.h:578
int get_per() const
Definition: character.cpp:4135
int get_speed() const override
Definition: character.cpp:4192
float get_proficiency_practice(const proficiency_id &prof) const
void mod_moves(int nmoves)
Definition: creature.cpp:2008
void set_moves(int nmoves)
Definition: creature.cpp:2012
float forward_velocity() const
void cruise_thrust(int amount)
float handling_difficulty() const
Returns roughly driving skill level at which there is no chance of fumbling.
Definition: vehicle.cpp:4807
static const proficiency_id proficiency_prof_boat_pilot("prof_boat_pilot")
static const proficiency_id proficiency_prof_driver("prof_driver")

References _, Character::add_msg_if_player(), cruise_thrust(), Character::dex_cur, forward_velocity(), Character::get_dex(), Creature::get_moves(), Character::get_per(), Character::get_proficiency_practice(), Character::get_skill_level(), Character::get_speed(), handling_difficulty(), Character::has_proficiency(), in_deep_water, tileray::init(), is_rotorcraft(), m_bad, m_info, m_warning, max(), min(), Creature::mod_moves(), move, name, one_in(), Character::practice(), proficiency_prof_boat_pilot, proficiency_prof_driver, rng(), rng_float(), Creature::set_moves(), skidding, skill_driving, vehicles::steer_increment, steering_effectiveness(), thrust(), turn(), turn_dir, valid_wheel_config(), velocity, point::x, and point::y.

Referenced by do_autodrive(), and pldrive().

◆ pos_bub()

tripoint_bub_ms vehicle::pos_bub ( ) const

Definition at line 3436 of file vehicle.cpp.

3437 {
3438  // TODO: fix point types
3439  return tripoint_bub_ms( global_pos3() );
3440 }

References global_pos3().

Referenced by bub_part_pos(), map::displace_vehicle(), vehicle_folding_activity_actor::fold_vehicle(), game::grabbed_veh_move(), and shed_loose_parts().

◆ possibly_recover_from_skid()

void vehicle::possibly_recover_from_skid ( )

Definition at line 1551 of file vehicle_move.cpp.

1552 {
1553  if( last_turn > 13_degrees ) {
1554  // Turning on the initial skid is delayed, so move==face, initially. This filters out that case.
1555  return;
1556  }
1557 
1558  rl_vec2d mv = move_vec();
1559  rl_vec2d fv = face_vec();
1560  float dot = mv.dot_product( fv );
1561  // Threshold of recovery is Gaussianesque.
1562 
1563  if( std::fabs( dot ) * 100 > dice( 9, 20 ) ) {
1564  add_msg( _( "The %s recovers from its skid." ), name );
1565  // face_vec takes over.
1566  skidding = false;
1567  // Wheels absorb horizontal velocity.
1568  velocity *= dot;
1569  if( dot < -.8 ) {
1570  // Pointed backwards, velo-wise.
1571  // Move backwards.
1572  velocity *= -1;
1573  }
1574 
1575  move = face;
1576  }
1577 }

References _, add_msg(), dice(), dot(), rl_vec2d::dot_product(), units::fabs(), face, face_vec(), last_turn, move, move_vec(), name, skidding, and velocity.

Referenced by map::move_vehicle().

◆ power_parts()

void vehicle::power_parts ( )

Definition at line 5236 of file vehicle.cpp.

5237 {
5239  // Things that drain energy: engines and accessories.
5240  units::power engine_epower = total_engine_epower();
5241  units::power epower = engine_epower + total_accessory_epower() + total_alternator_epower();
5242 
5243  int delta_energy_bat = power_to_energy_bat( epower, 1_turns );
5244  Character &player_character = get_player_character();
5245 
5246  if( !reactors.empty() ) {
5247  // Reactors trigger only on demand -- that is, if they can fill up a battery in the vehicle or any connected vehicles.
5248  // Check the entire graph of connected vehicles to determine power output.
5249  int battery_left;
5250  int battery_capacity;
5251  std::tie( battery_left, battery_capacity ) = connected_battery_power_level();
5252  int storage_deficit_bat = std::max( 0, battery_capacity - battery_left - delta_energy_bat );
5253  if( storage_deficit_bat > 0 ) {
5254  // Still not enough surplus epower to fully charge battery
5255  // Produce additional epower from any reactors
5256  bool reactor_working = false;
5257  bool reactor_online = false;
5258  for( const int p : reactors ) {
5259  vehicle_part &vp = parts[p];
5260  // Check whether the reactor is on. If not, move on.
5261  if( !vp.enabled ) {
5262  continue;
5263  }
5264  // Keep track whether or not the vehicle has any reactors activated
5265  reactor_online = true;
5266  // the amount of energy the reactor generates each turn
5267  const int gen_energy_bat = power_to_energy_bat( part_epower( vp ), 1_turns );
5268  if( vp.is_unavailable() ) {
5269  continue;
5270  } else if( vp.info().has_flag( STATIC( std::string( "PERPETUAL" ) ) ) ) {
5271  reactor_working = true;
5272  delta_energy_bat += std::min( storage_deficit_bat, gen_energy_bat );
5273  } else if( vp.ammo_remaining() > 0 ) {
5274  // Efficiency: one unit of fuel is this many units of battery
5275  // Note: One battery is 1 kJ
5276  const int efficiency = units::to_watt( vp.info().power );
5277  const int avail_fuel = vp.ammo_remaining() * efficiency;
5278  const int elem_energy_bat = std::min( gen_energy_bat, avail_fuel );
5279  // Cap output at what we can achieve and utilize
5280  const int reactors_output_bat = std::min( elem_energy_bat, storage_deficit_bat );
5281  // Fuel consumed in actual units of the resource
5282  int fuel_consumed = reactors_output_bat / efficiency;
5283  // Remainder has a chance of resulting in more fuel consumption
5284  fuel_consumed += x_in_y( reactors_output_bat % efficiency, efficiency ) ? 1 : 0;
5285  vp.ammo_consume( fuel_consumed, global_part_pos3( vp ) );
5286  reactor_working = true;
5287  delta_energy_bat += reactors_output_bat;
5288  }
5289  }
5290 
5291  if( !reactor_working && reactor_online ) {
5292  // All reactors out of fuel or destroyed
5293  for( int elem : reactors ) {
5294  parts[ elem ].enabled = false;
5295  }
5296  if( player_in_control( player_character ) || player_character.sees( global_pos3() ) ) {
5297  add_msg( _( "The %s's reactor dies!" ), name );
5298  }
5299  }
5300  }
5301  }
5302 
5303  int battery_deficit = 0;
5304  if( delta_energy_bat > 0 ) {
5305  // store epower surplus in battery
5306  charge_battery( delta_energy_bat );
5307  } else if( epower < 0_W ) {
5308  // draw epower deficit from battery
5309  battery_deficit = discharge_battery( std::abs( delta_energy_bat ) );
5310  }
5311 
5312  if( battery_deficit != 0 ) {
5313  // Scoops need a special case since they consume power during actual use
5314  for( const vpart_reference &vp : get_enabled_parts( "SCOOP" ) ) {
5315  vp.part().enabled = false;
5316  }
5317  // Rechargers need special case since they consume power on demand
5318  for( const vpart_reference &vp : get_enabled_parts( "RECHARGE" ) ) {
5319  vp.part().enabled = false;
5320  }
5321 
5323  vehicle_part &pt = vp.part();
5324  if( pt.info().epower < 0_W ) {
5325  pt.enabled = false;
5326  }
5327  }
5328 
5329  is_alarm_on = false;
5330  camera_on = false;
5331  if( player_in_control( player_character ) || player_character.sees( global_pos3() ) ) {
5332  add_msg( _( "The %s's battery dies!" ), name );
5333  }
5334  if( engine_epower < 0_W ) {
5335  // Not enough epower to run gas engine ignition system
5336  engine_on = false;
5337  if( player_in_control( player_character ) || player_character.sees( global_pos3() ) ) {
5338  add_msg( _( "The %s's engine dies!" ), name );
5339  }
5340  }
5341  noise_and_smoke( 0, 1_turns ); // refreshes this->vehicle_noise
5342  }
5343 }
int power_to_energy_bat(units::power power, const time_duration &d) const
Definition: vehicle.cpp:1146
void update_alternator_load()
Definition: vehicle.cpp:5205
int64_t battery_left(bool apply_loss=true) const
Definition: vehicle.cpp:5507
int charge_battery(int amount, bool apply_loss=true)
Charges batteries in connected vehicles/appliances.
Definition: vehicle.cpp:5521
@ VPFLAG_ENABLED_DRAINS_EPOWER
Definition: veh_type.h:102

References _, abs(), add_msg(), vehicle_part::ammo_consume(), vehicle_part::ammo_remaining(), battery_left(), camera_on, charge_battery(), connected_battery_power_level(), discharge_battery(), vehicle_part::enabled, engine_on, vpart_info::epower, get_enabled_parts(), get_player_character(), global_part_pos3(), global_pos3(), vpart_info::has_flag(), vehicle_part::info(), is_alarm_on, vehicle_part::is_unavailable(), max(), min(), name, noise_and_smoke(), part_epower(), parts, player_in_control(), vpart_info::power, power_to_energy_bat(), reactors, Character::sees(), STATIC, units::to_watt(), total_accessory_epower(), total_alternator_epower(), total_engine_epower(), update_alternator_load(), VPFLAG_ENABLED_DRAINS_EPOWER, and x_in_y().

Referenced by idle().

◆ power_to_energy_bat()

int vehicle::power_to_energy_bat ( units::power  power,
const time_duration d 
) const
private

Definition at line 1146 of file vehicle.cpp.

1147 {
1148  units::energy produced = power * d;
1149  int produced_kj = roll_remainder( units::to_millijoule( produced ) / 1000000.0 );
1150  return produced_kj;
1151 }
constexpr value_type to_millijoule(const quantity< value_type, energy_in_millijoule_tag > &v)
Definition: units.h:566
quantity< std::int64_t, power_in_milliwatt_tag > power
Definition: units_fwd.h:57

References roll_remainder(), and units::to_millijoule().

Referenced by power_parts(), print_fuel_indicator(), start_engine(), and update_time().

◆ precalc_mounts()

void vehicle::precalc_mounts ( int  idir,
const units::angle dir,
const point pivot 
)

Definition at line 3338 of file vehicle.cpp.

3340 {
3341  if( idir < 0 || idir > 1 ) {
3342  idir = 0;
3343  }
3344  tileray tdir( dir );
3345  std::unordered_map<point, tripoint> mount_to_precalc;
3346  for( vehicle_part &p : parts ) {
3347  if( p.removed ) {
3348  continue;
3349  }
3350  auto q = mount_to_precalc.find( p.mount );
3351  if( q == mount_to_precalc.end() ) {
3352  coord_translate( tdir, pivot, p.mount, p.precalc[idir] );
3353  mount_to_precalc.insert( { p.mount, p.precalc[idir] } );
3354  } else {
3355  p.precalc[idir] = q->second;
3356  }
3357  }
3358  pivot_anchor[idir] = pivot;
3359  pivot_rotation[idir] = dir;
3360 }

References coord_translate(), parts, pivot_anchor, and pivot_rotation.

Referenced by veh_interact::complete_vehicle(), get_bounding_box(), game::grabbed_veh_move(), item::link_to(), map::move_vehicle(), refresh(), restore_folded_parts(), separate_from_grid(), and split_vehicles().

◆ precalculate_vehicle_turning()

void vehicle::precalculate_vehicle_turning ( units::angle  new_turn_dir,
bool  check_rail_direction,
ter_furn_flag  ter_flag_to_check,
int &  wheels_on_rail,
int &  turning_wheels_that_are_one_axis_counter 
) const

Precalculate vehicle turn.

Counts wheels that will land on ter_flag_to_check new_turn_dir - turn direction to calculate falling_only - is vehicle falling check_rail_direction - check if vehicle should land on diagonal/not rail tile (use for trucks only) ter_flag_to_check - terrain flag vehicle wheel should land on Results: &wheels_on_rail - resulting wheels that land on ter_flag_to_check &turning_wheels_that_are_one_axis_counter - number of wheels that are on one axis and will land on rail

Definition at line 1632 of file vehicle_move.cpp.

1635 {
1636  // The direction we're moving
1637  tileray mdir;
1638  // calculate direction after turn
1639  mdir.init( new_turn_dir );
1640  tripoint dp;
1641  bool is_diagonal_movement = std::lround( to_degrees( new_turn_dir ) ) % 90 == 45;
1642 
1643  if( std::abs( velocity ) >= 20 ) {
1644  mdir.advance( velocity < 0 ? -1 : 1 );
1645  dp.x = mdir.dx();
1646  dp.y = mdir.dy();
1647  }
1648 
1649  // number of wheels that will land on rail
1650  wheels_on_rail = 0;
1651 
1652  // used to count wheels that will land on different axis
1653  int yVal = INT_MAX;
1654  /*
1655  number of wheels that are on one axis and will land on rail
1656  (not sometimes correct, for vehicle with 4 wheels, wheels_on_rail==3
1657  this can get 1 or 2 depending on position inaxis .wheelcache
1658  */
1659  turning_wheels_that_are_one_axis = 0;
1660 
1661  map &here = get_map();
1662  for( int part_index : wheelcache ) {
1663  const auto &wheel = parts[ part_index ];
1664  bool rails_ahead = true;
1665  tripoint wheel_point;
1666  coord_translate( mdir.dir(), this->pivot_point(), wheel.mount,
1667  wheel_point );
1668 
1669  tripoint wheel_tripoint = global_pos3() + wheel_point;
1670 
1671  // maximum number of incorrect tiles for this type of turn(diagonal or not)
1672  const int allowed_incorrect_tiles_diagonal = 1;
1673  const int allowed_incorrect_tiles_not_diagonal = 2;
1674  int incorrect_tiles_diagonal = 0;
1675  int incorrect_tiles_not_diagonal = 0;
1676 
1677  // check if terrain under the wheel and in direction of moving is rails
1678  for( int try_num = 0; try_num < 3; try_num++ ) {
1679  // advance precalculated wheel position 1 time in direction of moving
1680  wheel_tripoint += dp;
1681 
1682  if( !here.has_flag_ter_or_furn( ter_flag_to_check, wheel_tripoint ) ) {
1683  // this tile is not allowed, disallow turn
1684  rails_ahead = false;
1685  break;
1686  }
1687 
1688  // special case for rails
1689  if( check_rail_direction ) {
1690  const ter_str_id &terrain_at_wheel = here.ter( wheel_tripoint ).id();
1691  // check is it correct tile to turn into
1692  if( !is_diagonal_movement ) {
1693  const std::unordered_set<ter_str_id> diagonal_track_ters = { ter_t_railroad_track_d, ter_t_railroad_track_d1, ter_t_railroad_track_d2, ter_t_railroad_track_d_on_tie };
1694  if( diagonal_track_ters.find( terrain_at_wheel ) != diagonal_track_ters.end() ) {
1695  incorrect_tiles_not_diagonal++;
1696  }
1698  straight_track_ters.find( terrain_at_wheel ) != straight_track_ters.end() ) {
1699  incorrect_tiles_not_diagonal++;
1700  }
1701  if( incorrect_tiles_diagonal > allowed_incorrect_tiles_diagonal ||
1702  incorrect_tiles_not_diagonal > allowed_incorrect_tiles_not_diagonal ) {
1703  rails_ahead = false;
1704  break;
1705  }
1706  }
1707  }
1708  // found a wheel that turns correctly on rails
1709  if( rails_ahead ) {
1710  // if wheel that lands on rail still not found
1711  if( yVal == INT_MAX ) {
1712  // store mount point.y of wheel
1713  yVal = wheel.mount.y;
1714  }
1715  if( yVal == wheel.mount.y ) {
1716  turning_wheels_that_are_one_axis++;
1717  }
1718  wheels_on_rail++;
1719  }
1720  }
1721 }
const string_id< T > & id() const
Definition: ammo_effect.cpp:33
constexpr double to_degrees(const units::angle v)
Definition: units.h:757
static const ter_str_id ter_t_railroad_track_d("t_railroad_track_d")
static const ter_str_id ter_t_railroad_track_h("t_railroad_track_h")
static const ter_str_id ter_t_railroad_track_d1("t_railroad_track_d1")
static const ter_str_id ter_t_railroad_track("t_railroad_track")
static const ter_str_id ter_t_railroad_track_h_on_tie("t_railroad_track_h_on_tie")
static const ter_str_id ter_t_railroad_track_v("t_railroad_track_v")
static const ter_str_id ter_t_railroad_track_d2("t_railroad_track_d2")
static const ter_str_id ter_t_railroad_track_d_on_tie("t_railroad_track_d_on_tie")
static const ter_str_id ter_t_railroad_track_v_on_tie("t_railroad_track_v_on_tie")
static const ter_str_id ter_t_railroad_track_on_tie("t_railroad_track_on_tie")

References abs(), tileray::advance(), coord_translate(), tileray::dir(), tileray::dx(), tileray::dy(), get_map(), global_pos3(), map::has_flag_ter_or_furn(), int_id< T >::id(), tileray::init(), parts, map::ter(), ter_t_railroad_track, ter_t_railroad_track_d, ter_t_railroad_track_d1, ter_t_railroad_track_d2, ter_t_railroad_track_d_on_tie, ter_t_railroad_track_h, ter_t_railroad_track_h_on_tie, ter_t_railroad_track_on_tie, ter_t_railroad_track_v, ter_t_railroad_track_v_on_tie, units::to_degrees(), velocity, wheelcache, tripoint::x, and tripoint::y.

Referenced by allow_auto_turn_on_rails(), and allow_manual_turn_on_rails().

◆ precollision_check()

bool vehicle::precollision_check ( units::angle angle,
map here,
bool  follow_protocol 
)

Definition at line 790 of file vehicle.cpp.

791 {
792  if( !precollision_on ) {
793  return false;
794  }
795  Character &player_character = get_player_character();
796  // now we got the angle to the target, we can work out when we are heading towards disaster.
797  // Check the tileray in the direction we need to head towards.
798  std::set<point> points_to_check = immediate_path( angle );
799  bool stop = false;
800  creature_tracker &creatures = get_creature_tracker();
801  for( const point &pt_elem : points_to_check ) {
802  point elem = here.getlocal( pt_elem );
803  if( stop ) {
804  break;
805  }
806  const optional_vpart_position ovp = here.veh_at( tripoint( elem, sm_pos.z ) );
807  if( here.impassable_ter_furn( tripoint( elem, sm_pos.z ) ) || ( ovp &&
808  &ovp->vehicle() != this ) ) {
809  stop = true;
810  break;
811  }
812  if( elem == player_character.pos().xy() ) {
813  if( follow_protocol || player_character.in_vehicle ) {
814  continue;
815  } else {
816  stop = true;
817  break;
818  }
819  }
820  bool its_a_pet = false;
821  if( creatures.creature_at( tripoint( elem, sm_pos.z ) ) ) {
822  npc *guy = creatures.creature_at<npc>( tripoint( elem, sm_pos.z ) );
823  if( guy && !guy->in_vehicle ) {
824  stop = true;
825  break;
826  }
827  for( const vehicle_part &p : parts ) {
828  monster *mon = get_monster( index_of_part( &p ) );
829  if( mon && mon->pos().xy() == elem ) {
830  its_a_pet = true;
831  break;
832  }
833  }
834  if( !its_a_pet ) {
835  stop = true;
836  break;
837  }
838  }
839  }
840  return stop;
841 }
std::set< point > immediate_path(const units::angle &rotate=0_degrees)
Definition: vehicle.cpp:682

References creature_tracker::creature_at(), get_creature_tracker(), get_monster(), get_player_character(), map::getlocal(), immediate_path(), map::impassable_ter_furn(), Character::in_vehicle, index_of_part(), parts, Creature::pos(), precollision_on, sm_pos, stop(), tripoint, map::veh_at(), tripoint::xy(), and tripoint::z.

Referenced by drive_to_local_target().

◆ prepare_tool()

int vehicle::prepare_tool ( item tool) const

Flags item tool with PSEUDO, if it has MOD pocket then a pseudo_magazine_mod is installed and a pseudo_magazine is inserted into the magazine well pocket with however many ammo charges of the first ammo type required by the tool are available to this vehicle.

Parameters
toolthe tool item to modify
Returns
amount of ammo in the pseudo_magazine or 0

Definition at line 1742 of file vehicle_use.cpp.

1743 {
1744  tool.set_flag( STATIC( flag_id( "PSEUDO" ) ) );
1745 
1746  const auto &[ammo_itype_id, ammo_amount] = tool_ammo_available( tool.typeId() );
1747  if( ammo_itype_id.is_null() ) {
1748  return 0; // likely tool needs no ammo
1749  }
1750  item mag_mod( "pseudo_magazine_mod" );
1751  mag_mod.set_flag( STATIC( flag_id( "IRREMOVABLE" ) ) );
1752  if( !tool.put_in( mag_mod, pocket_type::MOD ).success() ) {
1753  debugmsg( "tool %s has no space for a %s, this is likely a bug",
1754  tool.typeId().str(), mag_mod.type->nname( 1 ) );
1755  }
1756  itype_id mag_type;
1757  if( tool.can_link_up() ) {
1758  mag_type = itype_pseudo_magazine;
1759  } else {
1760  mag_type = tool.magazine_default();
1761  }
1762  item mag( mag_type );
1763  mag.clear_items(); // no initial ammo
1764  if( !tool.put_in( mag, pocket_type::MAGAZINE_WELL ).success() ) {
1765  debugmsg( "inserting %s into %s's MAGAZINE_WELL pocket failed",
1766  mag.typeId().str(), tool.typeId().str() );
1767  return 0;
1768  }
1769 
1770  const int ammo_capacity = tool.ammo_capacity( ammo_itype_id->ammo->type );
1771  const int ammo_count = std::min( ammo_amount, ammo_capacity );
1772 
1773  tool.ammo_set( ammo_itype_id, ammo_count );
1774 
1775  add_msg_debug( debugmode::DF_VEHICLE, "prepared vehtool %s with %d %s",
1776  tool.typeId().str(), ammo_count, ammo_itype_id.str() );
1777 
1778  return ammo_count;
1779 }
ret_val< void > put_in(const item &payload, pocket_type pk_type, bool unseal_pockets=false, Character *carrier=nullptr)
Puts the given item into this one.
Definition: item.cpp:1784
int ammo_capacity(const ammotype &ammo, bool include_linked=false) const
ammo capacity for a specific ammo
Definition: item.cpp:10801
itype_id magazine_default(bool conversion=false) const
Get the default magazine type (if any) for the current effective ammo type.
Definition: item.cpp:11185
itype_id typeId() const
return the unique identifier of the items underlying type
Definition: item.cpp:11850
item & ammo_set(const itype_id &ammo, int qty=-1)
Filter setting the ammo for this instance Any existing ammo is removed.
Definition: item.cpp:719
bool can_link_up() const
Returns true if the item is/has a cable that can link up to other things. Should usually be called be...
Definition: item.cpp:13319
static const itype_id itype_pseudo_magazine("pseudo_magazine")

References add_msg_debug, item::ammo_capacity(), item::ammo_set(), item::can_link_up(), item::clear_items(), debugmsg, debugmode::DF_VEHICLE, flag_id, itype_pseudo_magazine, item::magazine_default(), MAGAZINE_WELL, min(), MOD, itype::nname(), item::put_in(), item::set_flag(), STATIC, string_id< T >::str(), ret_val_common::success(), tool_ammo_available(), item::type, and item::typeId().

Referenced by prepare_tools(), and use_vehicle_tool().

◆ prepare_tools()

std::map< item, int > vehicle::prepare_tools ( const vehicle_part vp) const
Returns
pseudo- and attached tools available from this vehicle part, marked with PSEUDO flags, pseudo_magazine_mod and pseudo_magazine attached, magazines filled with the first ammo type required by the tool. pseudo tools are mapped to their hotkey if exists.

Definition at line 5937 of file vehicle.cpp.

5938 {
5939  std::map<item, int> res;
5940  for( const std::pair<itype_id, int> &pair : vp.info().get_pseudo_tools() ) {
5941  item it( pair.first, calendar::turn );
5942  prepare_tool( it );
5943  res.emplace( it, pair.second > 0 ? pair.second : -1 );
5944  }
5945  for( const item &it_src : vp.tools ) {
5946  item it( it_src ); // make a copy
5947  prepare_tool( it );
5948  res.emplace( it, it.invlet > 0 ? it.invlet : 0 );
5949  }
5950  return res;
5951 }
int prepare_tool(item &tool) const
Flags item tool with PSEUDO, if it has MOD pocket then a pseudo_magazine_mod is installed and a pseud...

References vpart_info::get_pseudo_tools(), vehicle_part::info(), item::invlet, prepare_tool(), vehicle_part::tools, and calendar::turn.

Referenced by vpart_position::part_with_tool().

◆ print_fuel_indicator() [1/2]

void vehicle::print_fuel_indicator ( const catacurses::window win,
const point p,
const itype_id fuel_type,
bool  verbose = false,
bool  desc = false 
)
private

Prints a fuel gauge for a vehicle.

Parameters
winPointer to the window to draw in.
plocation to draw at.
fuel_typeID of the fuel type to draw
verbosetrue if there should be anything after the gauge (either the %, or number)
desctrue if the name of the fuel should be at the end
fuel_usagesmap of fuel types to consumption for verbose

Definition at line 390 of file vehicle_display.cpp.

392 {
393  std::map<itype_id, units::energy> fuel_usages;
394  print_fuel_indicator( win, p, fuel_type, fuel_usages, verbose, desc );
395 }
void print_fuel_indicator(const catacurses::window &w, const point &p, const itype_id &fuel_type, bool verbose=false, bool desc=false)
Prints a fuel gauge for a vehicle.

Referenced by print_fuel_indicators().

◆ print_fuel_indicator() [2/2]

void vehicle::print_fuel_indicator ( const catacurses::window w,
const point p,
const itype_id fuel_type,
std::map< itype_id, units::energy fuel_usages,
bool  verbose = false,
bool  desc = false 
)
private

Definition at line 397 of file vehicle_display.cpp.

401 {
402  static constexpr std::array<char, 5> fsyms = { 'E', '\\', '|', '/', 'F' };
403  nc_color col_indf1 = c_light_gray;
404  int cap = fuel_capacity( fuel_type );
405  int f_left = fuel_left( fuel_type );
406  nc_color f_color = item::find_type( fuel_type )->color;
407  // NOLINTNEXTLINE(cata-text-style): not an ellipsis
408  mvwprintz( win, p, col_indf1, "E...F" );
409  int amnt = cap > 0 ? f_left * 99 / cap : 0;
410  int indf = ( amnt / 20 ) % 5;
411  mvwprintz( win, p + point( indf, 0 ), f_color, "%c", fsyms[indf] );
412  if( verbose ) {
413  if( debug_mode || cap == 0 ) {
414  mvwprintz( win, p + point( 6, 0 ), f_color, "%d/%d", f_left, cap );
415  } else {
416  mvwprintz( win, p + point( 6, 0 ), f_color, "%d", f_left * 100 / cap );
417  wprintz( win, c_light_gray, "%c", 045 );
418  }
419  }
420  if( desc ) {
421  wprintz( win, c_light_gray, " - %s", item::nname( fuel_type ) );
422  }
423  if( verbose ) {
424  auto fuel_data = fuel_usages.find( fuel_type );
425  int rate = 0;
426  std::string units;
427  if( fuel_data != fuel_usages.end() ) {
428  rate = consumption_per_hour( fuel_type, fuel_data->second );
429  units = _( "mL" );
430  }
431  if( fuel_type == itype_battery ) {
432  rate += power_to_energy_bat( net_battery_charge_rate( /* include_reactors = */ true ), 1_hours );
433  units = _( "kJ" );
434  }
435  if( rate != 0 && cap != 0 ) {
436  int tank_use = 0;
437  nc_color tank_color = c_light_green;
438  std::string tank_goal = _( "full" );
439  if( rate > 0 ) {
440  tank_use = cap - f_left;
441  if( !tank_use ) {
442  return;
443  }
444  } else {
445  if( !f_left ) {
446  return;
447  }
448  tank_use = f_left;
449  tank_color = c_light_red;
450  tank_goal = _( "empty" );
451  }
452 
453  // promote to double so esimate doesn't overflow for high fuel values
454  // 3600 * tank_use overflows signed 32 bit when tank_use is over ~596523
455  double turns = to_turns<double>( 60_minutes );
456  time_duration estimate = time_duration::from_turns( turns * tank_use / std::abs( rate ) );
457 
458  if( debug_mode ) {
459  wprintz( win, tank_color, _( ", %d %s(%4.2f%%)/hour, %s until %s" ),
460  rate, units, 100.0 * rate / cap, to_string_clipped( estimate ), tank_goal );
461  } else {
462  wprintz( win, tank_color, _( ", %3.1f%% / hour, %s until %s" ),
463  100.0 * rate / cap, to_string_clipped( estimate ), tank_goal );
464  }
465  }
466  }
467 }
static std::string to_string_clipped(const int num, const clipped_unit type, const clipped_align align)
Definition: calendar.cpp:427
static std::string nname(const itype_id &id, unsigned int quantity=1)
Returns the translated item name for the item with given id.
Definition: item.cpp:14557
int fuel_capacity(const itype_id &ftype) const
Definition: vehicle.cpp:3581
int consumption_per_hour(const itype_id &ftype, units::energy fuel_per_s) const
Definition: vehicle.cpp:3684
#define c_light_gray
Definition: color.h:17
#define c_light_green
Definition: color.h:26
bool debug_mode
Extended debugging mode, can be toggled during game.
Definition: debug.cpp:210
Definition: units.cpp:9
void mvwprintz(const catacurses::window &w, const point &p, const nc_color &FG, const std::string &text)
Definition: output.cpp:3290
void wprintz(const catacurses::window &w, const nc_color &FG, const std::string &text)
Definition: output.cpp:3298
static const itype_id itype_battery("battery")

References _, abs(), c_light_gray, c_light_green, c_light_red, itype::color, consumption_per_hour(), debug_mode, item::find_type(), time_duration::from_turns(), fuel_capacity(), fuel_left(), itype_battery, mvwprintz(), net_battery_charge_rate(), item::nname(), point, power_to_energy_bat(), to_string_clipped(), and wprintz().

◆ print_fuel_indicators()

void vehicle::print_fuel_indicators ( const catacurses::window win,
const point p,
int  start_index = 0,
bool  fullsize = false,
bool  verbose = false,
bool  desc = false,
bool  isHorizontal = false 
)

Prints all of the fuel indicators of the vehicle.

Parameters
winPointer to the window to draw in.
plocation to draw at.
start_indexStarting index in array of fuel gauges to start reading from
fullsizetrue if it's expected to print multiple rows
verbosetrue if there should be anything after the gauge (either the %, or number)
desctrue if the name of the fuel should be at the end
isHorizontaltrue if the menu is not vertical

Definition at line 343 of file vehicle_display.cpp.

345 {
346  auto fuels = get_printable_fuel_types();
347  if( fuels.empty() ) {
348  return;
349  }
350  if( !fullsize ) {
351  for( const int part_idx : engines ) {
352  const vehicle_part &vp = parts[part_idx];
353  // if only one display, print the first engine that's on and consumes power
354  if( is_engine_on( vp ) && !is_perpetual_type( vp ) && !is_engine_type( vp, fuel_type_muscle ) ) {
355  print_fuel_indicator( win, p, vp.fuel_current(), verbose, desc );
356  return;
357  }
358  }
359  // or print the first fuel if no engines
360  print_fuel_indicator( win, p, fuels.front(), verbose, desc );
361  return;
362  }
363 
364  int yofs = 0;
365  int max_gauge = ( isHorizontal ? 12 : 5 ) + start_index;
366  int max_size = std::min( static_cast<int>( fuels.size() ), max_gauge );
367 
368  for( int i = start_index; i < max_size; i++ ) {
369  const itype_id &f = fuels[i];
370  print_fuel_indicator( win, p + point( 0, yofs ), f, fuel_used_last_turn, verbose, desc );
371  yofs++;
372  }
373 
374  // check if the current index is less than the max size minus 12 or 5, to indicate that there's more
375  if( start_index < static_cast<int>( fuels.size() ) - ( isHorizontal ? 12 : 5 ) ) {
376  mvwprintz( win, p + point( 0, yofs ), c_light_green, ">" );
377  wprintz( win, c_light_gray, " for more" );
378  }
379 }
std::vector< itype_id > get_printable_fuel_types() const
Returns an array of fuel types that can be printed.
static const itype_id fuel_type_muscle("muscle")

References c_light_gray, c_light_green, engines, vehicle_part::fuel_current(), fuel_type_muscle, fuel_used_last_turn, get_printable_fuel_types(), is_engine_on(), is_engine_type(), is_perpetual_type(), min(), mvwprintz(), parts, point, print_fuel_indicator(), and wprintz().

Referenced by veh_interact::display_stats(), and veh_app_interact::draw_info().

◆ print_part_list()

int vehicle::print_part_list ( const catacurses::window win,
int  y1,
int  max_y,
int  width,
int  p,
int  hl = -1,
bool  detail = false,
bool  include_fakes = true 
) const

Prints a list of all parts to the screen inside of a boxed window, possibly highlighting a selected one.

Parameters
winThe window to draw in.
y1The y-coordinate to start drawing at.
max_yDraw no further than this y-coordinate.
widthThe width of the window.
pThe index of the part being examined.
hlThe index of the part to highlight (if any).
detailWhether or not to show detailed contents for fuel components.

Definition at line 143 of file vehicle_display.cpp.

145 {
146  if( p < 0 || p >= static_cast<int>( parts.size() ) ) {
147  return y1;
148  }
149  std::vector<int> pl = this->parts_at_relative( parts[p].mount, true, include_fakes );
150  int y = y1;
151  for( size_t i = 0; i < pl.size(); i++ ) {
152  const vehicle_part &vp = parts[pl[i]];
153  const vpart_info &vpi = vp.info();
154  if( !vp.is_real_or_active_fake() ) {
155  continue;
156  }
157  if( y >= max_y ) {
158  mvwprintz( win, point( 1, y ), c_yellow, _( "More parts here…" ) );
159  ++y;
160  break;
161  }
162 
163  std::string partname = vp.name();
164 
165  if( vp.is_fuel_store() && !vp.ammo_current().is_null() ) {
166  if( detail ) {
167  if( vp.ammo_current() == itype_battery ) {
168  partname += string_format( _( " (%s/%s charge)" ), vp.ammo_remaining(),
169  vp.ammo_capacity( ammo_battery ) );
170  } else if( vp.ammo_current()->stack_size > 0 ) {
171  const itype *pt_ammo_cur = item::find_type( vp.ammo_current() );
172  auto stack = units::legacy_volume_factor / pt_ammo_cur->stack_size;
173  partname += string_format( _( " (%.1fL %s)" ),
174  round_up( units::to_liter( vp.ammo_remaining() * stack ), 1 ),
175  item::nname( vp.ammo_current() ) );
176  }
177  } else {
178  partname += string_format( " (%s)", item::nname( vp.ammo_current() ) );
179  }
180  }
181 
182  if( vpi.has_flag( VPFLAG_CARGO ) ) {
183  const vehicle_stack vs = get_items( vp );
184  //~ used/total volume of a cargo vehicle part
185  partname += string_format( _( " (vol: %s/%s %s)" ),
187  format_volume( vs.max_volume() ),
188  volume_units_abbr() );
189  }
190 
191  const bool armor = vpi.has_flag( VPFLAG_ARMOR );
192  std::string left_sym;
193  std::string right_sym;
194  if( armor ) {
195  left_sym = "(";
196  right_sym = ")";
197  } else if( vpi.location == part_location_structure ) {
198  left_sym = "[";
199  right_sym = "]";
200  } else {
201  left_sym = "-";
202  right_sym = "-";
203  }
204  nc_color sym_color = static_cast<int>( i ) == hl ? hilite( c_light_gray ) : c_light_gray;
205  mvwprintz( win, point( 1, y ), sym_color, left_sym );
206  trim_and_print( win, point( 2, y ), getmaxx( win ) - 4,
207  static_cast<int>( i ) == hl ? hilite( c_light_gray ) : c_light_gray, partname );
208  wprintz( win, sym_color, right_sym );
209 
210  if( i == 0 && vpart_position( const_cast<vehicle &>( *this ), pl[i] ).is_inside() ) {
211  //~ indicates that a vehicle part is inside
212  mvwprintz( win, point( width - 2 - utf8_width( _( "Interior" ) ), y ), c_light_gray,
213  _( "Interior" ) );
214  } else if( i == 0 ) {
215  //~ indicates that a vehicle part is outside
216  mvwprintz( win, point( width - 2 - utf8_width( _( "Exterior" ) ), y ), c_light_gray,
217  _( "Exterior" ) );
218  }
219  y++;
220  }
221 
222  // print the label for this location
223  const std::optional<std::string> label = vpart_position( const_cast<vehicle &>( *this ),
224  p ).get_label();
225  if( label && y <= max_y ) {
226  mvwprintz( win, point( 1, y++ ), c_light_red, _( "Label: %s" ), label->c_str() );
227  }
228 
229  return y;
230 }
double round_up(double val, unsigned int dp)
Round a value up at a given decimal place.
int utf8_width(const std::string_view s, const bool ignore_tags)
units::volume stored_volume() const
Total volume of the items here.
Definition: item_stack.cpp:102
units::volume max_volume() const override
Maximum volume allowed here.
Definition: vehicle.cpp:202
std::optional< std::string > get_label() const
Definition: vehicle.cpp:2902
nc_color hilite(const nc_color &c)
Definition: color.cpp:546
#define c_yellow
Definition: color.h:30
int getmaxx(const window &win)
Definition: ncurses_def.cpp:91
Definition: assign.h:25
constexpr double to_liter(const volume &v)
Definition: units.h:321
std::string format_volume(const units::volume &volume)
Convert and format volume.
Definition: output.cpp:3231
void trim_and_print(const catacurses::window &w, const point &begin, const int width, const nc_color &base_color, const std::string &text, const report_color_error color_error)
Prints a single line of text.
Definition: output.cpp:268
int stack_size
Number of items per above volume for count_by_charges items.
Definition: itype.h:1408
Struct used for storing labels (easier to json opposed to a std::map<point, std::string>)
Definition: vehicle.h:687
const char * volume_units_abbr()
Create an abbreviated units label for a volume value.
static const std::string part_location_structure("structure")
static const ammotype ammo_battery("battery")

References _, ammo_battery, vehicle_part::ammo_capacity(), vehicle_part::ammo_current(), vehicle_part::ammo_remaining(), c_light_gray, c_light_red, c_yellow, item::find_type(), format_volume(), get_items(), vpart_position::get_label(), catacurses::getmaxx(), vpart_info::has_flag(), hilite(), vehicle_part::info(), vehicle_part::is_fuel_store(), string_id< T >::is_null(), vehicle_part::is_real_or_active_fake(), itype_battery, units::legacy_volume_factor, vpart_info::location, vehicle_stack::max_volume(), mvwprintz(), vehicle_part::name(), item::nname(), part_location_structure(), parts, parts_at_relative(), point, round_up(), itype::stack_size, item_stack::stored_volume(), string_format(), units::to_liter(), trim_and_print(), utf8_width(), volume_units_abbr(), VPFLAG_ARMOR, VPFLAG_CARGO, and wprintz().

Referenced by veh_interact::create_or_get_ui_adaptor(), and game::print_vehicle_info().

◆ print_speed_gauge()

void vehicle::print_speed_gauge ( const catacurses::window win,
const point p,
int  spacing = 0 
) const

Vehicle speed gauge.

Prints: target speed < current speed speed unit

Parameters
spacingSets size of space between components
Warning
if spacing is negative it is changed to 0

Definition at line 469 of file vehicle_display.cpp.

470 {
471  if( spacing < 0 ) {
472  spacing = 0;
473  }
474 
475  // Color is based on how much vehicle is straining beyond its safe velocity
476  const float strain = this->strain();
477  nc_color col_vel = strain <= 0 ? c_light_blue :
478  ( strain <= 0.2 ? c_yellow :
479  ( strain <= 0.4 ? c_light_red : c_red ) );
480  // Get cruising (target) velocity, and current (actual) velocity
481  int t_speed = static_cast<int>( convert_velocity( cruise_velocity, VU_VEHICLE ) );
482  int c_speed = static_cast<int>( convert_velocity( velocity, VU_VEHICLE ) );
483  auto ndigits = []( int value ) {
484  return value == 0 ? 1 :
485  ( value > 0 ?
486  static_cast<int>( std::log10( static_cast<double>( std::abs( value ) ) ) ) + 1 :
487  static_cast<int>( std::log10( static_cast<double>( std::abs( value ) ) ) ) + 2 );
488  };
489  const std::string type = get_option<std::string> ( "USE_METRIC_SPEEDS" );
490  int t_offset = ndigits( t_speed );
491  int c_offset = ndigits( c_speed );
492 
493  // Target cruising velocity in green
494  mvwprintz( win, p, c_light_green, "%d", t_speed );
495  mvwprintz( win, p + point( t_offset + spacing, 0 ), c_light_gray, "<" );
496  // Current velocity in color indicating engine strain
497  mvwprintz( win, p + point( t_offset + 1 + 2 * spacing, 0 ), col_vel, "%d", c_speed );
498  // Units of speed (mph, km/h, t/t)
499  mvwprintz( win, p + point( t_offset + c_offset + 1 + 3 * spacing, 0 ), c_light_gray, type );
500 }
@ VU_VEHICLE
Definition: cata_utility.h:55
double convert_velocity(int velocity, units_type vel_units)
Convert internal velocity units to units defined by user.
#define c_light_blue
Definition: color.h:27

References abs(), c_light_blue, c_light_gray, c_light_green, c_light_red, c_red, c_yellow, convert_velocity(), cruise_velocity, mvwprintz(), point, strain(), type, velocity, and VU_VEHICLE.

◆ print_vparts_descs()

void vehicle::print_vparts_descs ( const catacurses::window win,
int  max_y,
int  width,
int  p,
int &  start_at,
int &  start_limit 
) const

Prints a list of descriptions for all parts to the screen inside of a boxed window.

Parameters
winThe window to draw in.
max_yDraw no further than this y-coordinate.
widthThe width of the window.
pThe index of the part being examined.
start_atWhich vehicle part to start printing at.
start_limitthe part index beyond which the display is full

Definition at line 241 of file vehicle_display.cpp.

243 {
244  if( p < 0 || p >= static_cast<int>( parts.size() ) ) {
245  return;
246  }
247 
248  std::vector<int> pl = this->parts_at_relative( parts[p].mount, true );
249  std::string msg;
250 
251  int lines = 0;
252  /*
253  * start_at and start_limit interaction is little tricky
254  * start_at and start_limit start at 0 when moving to a new frame
255  * if all the descriptions are displayed in the window, start_limit stays at 0 and
256  * start_at is capped at 0 - so no scrolling at all.
257  * if all the descriptions aren't displayed, start_limit jumps to the last displayed part
258  * and the next scrollthrough can start there - so scrolling down happens.
259  * when the scroll reaches the point where all the remaining descriptions are displayed in
260  * the window, start_limit is set to start_at again.
261  * on the next attempted scrolldown, start_limit is set to the nth item, and start_at is
262  * capped to the nth item, so no more scrolling down.
263  * start_at can always go down, but never below 0, so scrolling up is only possible after
264  * some scrolling down has occurred.
265  * important! the calling function needs to track p, start_at, and start_limit, and set
266  * start_limit to 0 if p changes.
267  */
268  start_at = std::max( 0, std::min( start_at, start_limit ) );
269  if( start_at ) {
270  msg += std::string( "<color_yellow>" ) + "< " + _( "More parts here…" ) + "</color>\n";
271  lines += 1;
272  }
273  for( size_t i = start_at; i < pl.size(); i++ ) {
274  const vehicle_part &vp = parts[ pl [ i ] ];
275  std::string possible_msg;
276  const nc_color name_color = vp.is_broken() ? c_dark_gray : c_light_green;
277  possible_msg += colorize( vp.name(), name_color ) + "\n";
278  const nc_color desc_color = vp.is_broken() ? c_dark_gray : c_light_gray;
279  // -4 = -2 for left & right padding + -2 for "> "
280  int new_lines = 2 + vp.info().format_description( possible_msg, desc_color, width - 4 );
281  if( vp.has_flag( vp_flag::carrying_flag ) ) {
282  possible_msg += _( " Carrying a vehicle on a rack.\n" );
283  new_lines += 1;
284  }
285  if( vp.has_flag( vp_flag::carried_flag ) ) {
286  possible_msg += string_format( _( " Part of a %s carried on a rack.\n" ),
287  vp.carried_name() );
288  new_lines += 1;
289  }
290 
291  possible_msg += "</color>\n";
292  if( lines + new_lines <= max_y ) {
293  msg += possible_msg;
294  lines += new_lines;
295  start_limit = start_at;
296  } else {
297  msg += std::string( "<color_yellow>" ) + _( "More parts here…" ) + " >" + "</color>\n";
298  start_limit = i;
299  break;
300  }
301  }
302  werase( win );
303  // -2 for left & right padding
304  // NOLINTNEXTLINE(cata-use-named-point-constants)
305  fold_and_print( win, point( 1, 0 ), width - 2, c_light_gray, msg );
306  wnoutrefresh( win );
307 }
int format_description(std::string &msg, const nc_color &format_color, int width) const
Format the description for display.
Definition: veh_type.cpp:977
#define c_dark_gray
Definition: color.h:18
void wnoutrefresh(const window &win)
Definition: ncurses_def.cpp:67
void werase(const window &win)
Definition: ncurses_def.cpp:83
int fold_and_print(const catacurses::window &w, const point &begin, int width, const nc_color &base_color, const std::string &text, const char split)
Fold and print text in the given window.
Definition: output.cpp:379

References _, c_dark_gray, c_light_gray, c_light_green, carried_flag, vehicle_part::carried_name(), carrying_flag, colorize(), fold_and_print(), vpart_info::format_description(), vehicle_part::has_flag(), vehicle_part::info(), vehicle_part::is_broken(), max(), min(), vehicle_part::name(), parts, parts_at_relative(), point, string_format(), catacurses::werase(), and catacurses::wnoutrefresh().

Referenced by veh_interact::create_or_get_ui_adaptor().

◆ real_parts()

std::vector< std::reference_wrapper< const vehicle_part > > vehicle::real_parts ( ) const
private

Definition at line 8142 of file vehicle.cpp.

8143 {
8144  std::vector<std::reference_wrapper<const vehicle_part>> ret;
8145  for( const vehicle_part &vp : parts ) {
8146  if( vp.removed || vp.is_fake ) {
8147  continue;
8148  }
8149  ret.emplace_back( std::ref( vp ) );
8150  }
8151  return ret;
8152 }

References parts, and cata::hash64_detail::ret.

Referenced by find_vehicles_to_unrack(), get_folded_item(), and is_foldable().

◆ refresh()

void vehicle::refresh ( bool  remove_fakes = true)

Refreshes all caches and refinds all parts.

Used after the vehicle has had a part added or removed. Makes indices of different part types so they're easy to find. Also calculates power drain.

Definition at line 6179 of file vehicle.cpp.

6180 {
6181  if( no_refresh ) {
6182  return;
6183  }
6184 
6185  alternators.clear();
6186  engines.clear();
6187  reactors.clear();
6188  solar_panels.clear();
6189  wind_turbines.clear();
6190  sails.clear();
6191  water_wheels.clear();
6192  funnels.clear();
6193  emitters.clear();
6194  relative_parts.clear();
6195  loose_parts.clear();
6196  wheelcache.clear();
6197  rail_wheelcache.clear();
6198  rotors.clear();
6199  steering.clear();
6200  speciality.clear();
6201  floating.clear();
6202  batteries.clear();
6203  fuel_containers.clear();
6204  turret_locations.clear();
6205  mufflers.clear();
6206  planters.clear();
6207  accessories.clear();
6208  cable_ports.clear();
6209  control_req_parts.clear();
6210 
6211  alternator_load = 0;
6212  extra_drag = 0_W;
6213  all_wheels_on_one_axis = true;
6214  int first_wheel_y_mount = INT_MAX;
6215 
6216  // Used to sort part list so it displays properly when examining
6217  struct sort_veh_part_vector {
6218  vehicle *veh;
6219  inline bool operator()( const int p1, const int p2 ) const {
6220  return veh->part( p1 ).info().list_order < veh->part( p2 ).info().list_order;
6221  }
6222  } svpv = { this };
6223 
6224  mount_min.x = 123;
6225  mount_min.y = 123;
6226  mount_max.x = -123;
6227  mount_max.y = -123;
6228 
6229  int railwheel_xmin = INT_MAX;
6230  int railwheel_ymin = INT_MAX;
6231  int railwheel_xmax = INT_MIN;
6232  int railwheel_ymax = INT_MIN;
6233 
6235  smart_controller_state = std::nullopt;
6236 
6237  bool refresh_done = false;
6238 
6239  // Main loop over all vehicle parts.
6240  for( const vpart_reference &vp : get_all_parts() ) {
6241  const size_t p = vp.part_index();
6242  const vpart_info &vpi = vp.info();
6243  if( vp.part().removed ) {
6244  continue;
6245  }
6246  refresh_done = true;
6247 
6248  // Build map of point -> all parts in that point
6249  const point pt = vp.mount();
6250  mount_min.x = std::min( mount_min.x, pt.x );
6251  mount_min.y = std::min( mount_min.y, pt.y );
6252  mount_max.x = std::max( mount_max.x, pt.x );
6253  mount_max.y = std::max( mount_max.y, pt.y );
6254 
6255  // This will keep the parts at point pt sorted
6256  std::vector<int>::iterator vii = std::lower_bound( relative_parts[pt].begin(),
6257  relative_parts[pt].end(),
6258  static_cast<int>( p ), svpv );
6259  relative_parts[pt].insert( vii, p );
6260 
6261  //If it doesn't leak or it's health is less than 50% then The hull has been breached and the air is leaking out
6262  if( vpi.has_flag( VPFLAG_FLOATS ) && ( vpi.has_flag( VPFLAG_NO_LEAK ) ||
6263  !( vp.part().health_percent() < vp.part().floating_leak_threshold() ) ) ) {
6264  floating.push_back( p );
6265  }
6266 
6267  if( vp.part().is_unavailable() ) {
6268  continue;
6269  }
6270  if( vpi.has_flag( VPFLAG_ALTERNATOR ) ) {
6271  alternators.push_back( p );
6272  }
6273  if( vpi.has_flag( VPFLAG_ENGINE ) ) {
6274  engines.push_back( p );
6275  }
6276  if( vpi.has_flag( VPFLAG_REACTOR ) ) {
6277  reactors.push_back( p );
6278  }
6279  if( vpi.has_flag( VPFLAG_SOLAR_PANEL ) ) {
6280  solar_panels.push_back( p );
6281  }
6282  if( vpi.has_flag( VPFLAG_ROTOR ) ) {
6283  rotors.push_back( p );
6284  }
6285  if( vp.part().is_battery() ) {
6286  batteries.push_back( p );
6287  }
6288  if( vp.part().is_fuel_store( false ) ) {
6289  fuel_containers.push_back( p );
6290  }
6291  if( vp.part().is_turret() ) {
6292  turret_locations.push_back( p );
6293  }
6294  if( vpi.has_flag( "WIND_TURBINE" ) ) {
6295  wind_turbines.push_back( p );
6296  }
6297  if( vpi.has_flag( "WIND_POWERED" ) ) {
6298  sails.push_back( p );
6299  }
6300  if( vpi.has_flag( "WATER_WHEEL" ) ) {
6301  water_wheels.push_back( p );
6302  }
6303  if( vpi.has_flag( "FUNNEL" ) ) {
6304  funnels.push_back( p );
6305  }
6306  if( vpi.has_flag( "UNMOUNT_ON_MOVE" ) || vpi.has_flag( VPFLAG_POWER_TRANSFER ) ) {
6307  loose_parts.push_back( p );
6308  }
6309  if( !vpi.emissions.empty() || !vpi.exhaust.empty() ) {
6310  emitters.push_back( p );
6311  }
6312  if( vpi.has_flag( VPFLAG_WHEEL ) ) {
6313  wheelcache.push_back( p );
6314  }
6315  if( vpi.has_flag( "SMART_ENGINE_CONTROLLER" ) && vp.part().enabled ) {
6317  }
6318  if( vpi.has_flag( VPFLAG_WHEEL ) && vpi.has_flag( VPFLAG_RAIL ) ) {
6319  rail_wheelcache.push_back( p );
6320  if( first_wheel_y_mount == INT_MAX ) {
6321  first_wheel_y_mount = vp.part().mount.y;
6322  }
6323  if( first_wheel_y_mount != vp.part().mount.y ) {
6324  // vehicle have wheels on different axis
6325  all_wheels_on_one_axis = false;
6326  }
6327 
6328  railwheel_xmin = std::min( railwheel_xmin, pt.x );
6329  railwheel_ymin = std::min( railwheel_ymin, pt.y );
6330  railwheel_xmax = std::max( railwheel_xmax, pt.x );
6331  railwheel_ymax = std::max( railwheel_ymax, pt.y );
6332  }
6333  if( ( vpi.has_flag( "STEERABLE" ) && part_with_feature( pt, "STEERABLE", true ) != -1 ) ||
6334  vpi.has_flag( "TRACKED" ) ) {
6335  // TRACKED contributes to steering effectiveness but
6336  // (a) doesn't count as a steering axle for install difficulty
6337  // (b) still contributes to drag for the center of steering calculation
6338  steering.push_back( p );
6339  }
6340  if( vpi.has_flag( "SECURITY" ) ) {
6341  speciality.push_back( p );
6342  }
6343  if( vp.part().enabled && vpi.has_flag( "EXTRA_DRAG" ) ) {
6344  extra_drag += vpi.power;
6345  }
6346  if( vpi.has_flag( "EXTRA_DRAG" ) && ( vpi.has_flag( "WIND_TURBINE" ) ||
6347  vpi.has_flag( "WATER_WHEEL" ) ) ) {
6348  extra_drag += vpi.power;
6349  }
6350  if( camera_on && vpi.has_flag( "CAMERA" ) ) {
6351  vp.part().enabled = true;
6352  } else if( !camera_on && vpi.has_flag( "CAMERA" ) ) {
6353  vp.part().enabled = false;
6354  }
6355  if( vpi.has_flag( "TURRET" ) && !has_part( global_part_pos3( vp.part() ), "TURRET_CONTROLS" ) ) {
6356  vp.part().enabled = false;
6357  }
6358  if( vpi.has_flag( "MUFFLER" ) ) {
6359  mufflers.push_back( p );
6360  }
6361  if( vpi.has_flag( "PLANTER" ) ) {
6362  planters.push_back( p );
6363  }
6364  if( vpi.has_flag( VPFLAG_ENABLED_DRAINS_EPOWER ) ) {
6365  accessories.push_back( p );
6366  }
6367  if( vpi.has_flag( VPFLAG_CABLE_PORTS ) || vpi.has_flag( VPFLAG_APPLIANCE ) ) {
6368  cable_ports.push_back( p );
6369  }
6370  if( vpi.has_control_req() ) {
6371  control_req_parts.push_back( p );
6372  }
6373  }
6374 
6375  rail_wheel_bounding_box.p1 = point( railwheel_xmin, railwheel_ymin );
6376  rail_wheel_bounding_box.p2 = point( railwheel_xmax, railwheel_ymax );
6377  front_left.x = mount_max.x;
6378  front_left.y = mount_min.y;
6380 
6381  if( !refresh_done ) {
6385  }
6386 
6387  const auto need_fake_part = [&]( const point & real_mount, const std::string & flag ) {
6388  int real = part_with_feature( real_mount, flag, true );
6389  if( real >= 0 && real < part_count() ) {
6390  return real;
6391  }
6392  return -1;
6393  };
6394  const auto add_fake_part = [&]( const point & real_mount, const std::string & flag ) {
6395  // to be eligible for a fake copy, you have to be an obstacle or protrusion
6396  const int real_index = need_fake_part( real_mount, flag );
6397  if( real_index < 0 ) {
6398  return;
6399  }
6400  // find neighbor info for current mount
6401  vpart_edge_info edge_info = get_edge_info( real_mount );
6402  // add fake mounts based on the edge info
6403  if( edge_info.is_edge_mount() ) {
6404  // get a copy of the real part and install it as an inactive fake part
6405  vehicle_part &part_real = parts.at( real_index );
6406  if( part_real.has_fake &&
6407  static_cast<size_t>( part_real.fake_part_at ) < parts.size() ) {
6408  relative_parts[ parts[ part_real.fake_part_at ].mount ].push_back(
6409  part_real.fake_part_at );
6410  return;
6411  }
6412  vehicle_part part_fake( parts.at( real_index ) );
6413  part_real.has_fake = true;
6414  part_fake.is_fake = true;
6415  part_fake.fake_part_to = real_index;
6416  part_fake.mount += edge_info.is_left_edge() ? point_north : point_south;
6417  if( part_real.info().has_flag( "PROTRUSION" ) ) {
6418  for( const int vp : relative_parts.at( part_real.mount ) ) {
6419  if( parts.at( vp ).is_fake ) {
6420  part_fake.fake_protrusion_on = vp;
6421  break;
6422  }
6423  }
6424  }
6425  int fake_index = parts.size();
6426  part_real.fake_part_at = fake_index;
6427  fake_parts.push_back( fake_index );
6428  relative_parts[ part_fake.mount ].push_back( fake_index );
6429  edges.emplace( real_mount, edge_info );
6430  parts.push_back( std::move( part_fake ) );
6431  }
6432  };
6433  // re-install fake parts - this could be done in a separate function, but we want to
6434  // guarantee that the fake parts were removed before being added
6435  if( remove_fakes && !has_tag( "wreckage" ) && !is_appliance() ) {
6436  // add all the obstacles first
6437  for( const std::pair <const point, std::vector<int>> &rp : relative_parts ) {
6438  add_fake_part( rp.first, "OBSTACLE" );
6439  }
6440  // then add protrusions that hanging on top of fake obstacles.
6441 
6442  std::vector<int> current_fakes = fake_parts; // copy, not a reference
6443  for( const int fake_index : current_fakes ) {
6444  add_fake_part( parts.at( fake_index ).mount, "PROTRUSION" );
6445  }
6446 
6447  // add fake camera parts so vision isn't blocked by fake parts
6448  for( const std::pair <const point, std::vector<int>> &rp : relative_parts ) {
6449  add_fake_part( rp.first, "CAMERA" );
6450  }
6451  // add fake curtains so vision is correctly blocked
6452  for( const std::pair <const point, std::vector<int>> &rp : relative_parts ) {
6453  add_fake_part( rp.first, "OPAQUE" );
6454  }
6455  } else {
6456  // Always repopulate fake parts in relative_parts cache since we cleared it.
6457  for( const int fake_index : fake_parts ) {
6458  if( parts[fake_index].removed ) {
6459  continue;
6460  }
6461  point pt = parts[fake_index].mount;
6462  relative_parts[pt].push_back( fake_index );
6463  }
6464  }
6465 
6466  // NB: using the _old_ pivot point, don't recalc here, we only do that when moving!
6468  // update the fakes, and then repopulate the cache
6471  insides_dirty = true;
6472  zones_dirty = true;
6473  coeff_air_dirty = true;
6474  invalidate_mass();
6475  occupied_cache_pos = { -1, -1, -1 };
6477 }
std::vector< int > accessories
Definition: vehicle.h:2195
std::vector< int > steering
Definition: vehicle.h:2186
std::vector< int > sails
Definition: vehicle.h:2178
vpart_edge_info get_edge_info(const point &mount) const
Definition: vehicle.cpp:6479
std::vector< int > funnels
Definition: vehicle.h:2179
std::optional< smart_controller_cache > smart_controller_state
Definition: vehicle.h:2224
units::power extra_drag
Definition: vehicle.h:2298
std::vector< int > cable_ports
Definition: vehicle.h:2196
std::vector< int > turret_locations
Definition: vehicle.h:2192
void refresh_active_item_cache()
Definition: vehicle.cpp:6162
std::map< point, vpart_edge_info > edges
Definition: vehicle.h:2125
void update_active_fakes()
bool has_control_req() const
Returns whether or not the vehicle this part installed requires something to control.
Definition: veh_type.cpp:1156
int list_order
Definition: veh_type.h:458
@ end
Definition: input.h:95
bool is_edge_mount() const
Definition: vehicle.h:165
bool is_left_edge() const
Definition: vehicle.h:168
@ VPFLAG_ALTERNATOR
Definition: veh_type.h:87
@ VPFLAG_CABLE_PORTS
Definition: veh_type.h:111
@ VPFLAG_NO_LEAK
Definition: veh_type.h:83
@ VPFLAG_SOLAR_PANEL
Definition: veh_type.h:97
@ VPFLAG_FLOATS
Definition: veh_type.h:82
@ VPFLAG_APPLIANCE
Definition: veh_type.h:59
@ VPFLAG_RAIL
Definition: veh_type.h:108

References accessories, all_wheels_on_one_axis, alternator_load, alternators, batteries, cable_ports, camera_on, check_environmental_effects, coeff_air_dirty, control_req_parts, edges, vpart_info::emissions, emitters, keycode::end, engines, vpart_info::exhaust, extra_drag, vehicle_part::fake_part_at, vehicle_part::fake_part_to, fake_parts, vehicle_part::fake_protrusion_on, floating, front_left, front_right, fuel_containers, funnels, get_all_parts(), get_edge_info(), global_part_pos3(), vpart_info::has_control_req(), has_enabled_smart_controller, vehicle_part::has_fake, vpart_info::has_flag(), has_part(), has_tag(), vehicle_part::info(), insides_dirty, invalidate_mass(), is_appliance(), vpart_edge_info::is_edge_mount(), vehicle_part::is_fake, vpart_edge_info::is_left_edge(), vpart_info::list_order, loose_parts, max(), min(), vehicle_part::mount, mount_max, mount_min, mufflers, no_refresh, occupied_cache_pos, bounding_box::p1, bounding_box::p2, part(), part_count(), part_with_feature(), parts, pivot_anchor, pivot_rotation, planters, point, point_north, point_south, point_zero, vpart_info::power, precalc_mounts(), rail_wheel_bounding_box, rail_wheelcache, reactors, refresh_active_item_cache(), relative_parts, rotors, sails, smart_controller_state, solar_panels, speciality, steering, turret_locations, update_active_fakes(), VPFLAG_ALTERNATOR, VPFLAG_APPLIANCE, VPFLAG_CABLE_PORTS, VPFLAG_ENABLED_DRAINS_EPOWER, VPFLAG_ENGINE, VPFLAG_FLOATS, VPFLAG_NO_LEAK, VPFLAG_POWER_TRANSFER, VPFLAG_RAIL, VPFLAG_REACTOR, VPFLAG_ROTOR, VPFLAG_SOLAR_PANEL, VPFLAG_WHEEL, water_wheels, wheelcache, wind_turbines, point::x, point::y, and zones_dirty.

Referenced by activate_animal_follow(), activate_magical_follow(), damage_direct(), drive_to_local_target(), enable_refresh(), init_state(), install_part(), merge_rackable_vehicle(), merge_vehicle_parts(), part_removal_cleanup(), veh_menu::query(), remove_part(), restore_folded_parts(), shift_if_needed(), shift_parts(), split_vehicles(), start_engines(), stop_engines(), and vehicle().

◆ refresh_active_item_cache()

void vehicle::refresh_active_item_cache ( )

Definition at line 6162 of file vehicle.cpp.

6163 {
6164  // Need to manually backfill the active item cache since the part loader can't call its vehicle.
6165  for( const vpart_reference &vp : get_any_parts( VPFLAG_CARGO ) ) {
6166  vehicle_stack vs = vp.items();
6167  auto it = vs.begin();
6168  auto end = vs.end();
6169  for( ; it != end; ++it ) {
6170  active_items.add( *it, vp.mount() );
6171  }
6172  }
6173 }
cata::colony< item > * items
Definition: item_stack.h:27

References active_items, active_item_cache::add(), item_stack::begin(), keycode::end, item_stack::end(), get_any_parts(), item_stack::items, and VPFLAG_CARGO.

Referenced by refresh().

◆ refresh_insides()

void vehicle::refresh_insides ( )

Definition at line 7078 of file vehicle.cpp.

7079 {
7080  if( !insides_dirty ) {
7081  return;
7082  }
7083  insides_dirty = false;
7084  for( const vpart_reference &vpr : get_all_parts() ) {
7085  vehicle_part &vp = vpr.part();
7086  if( vp.removed ) {
7087  continue;
7088  }
7089  /* If there's no roof, or there is a roof but it's broken, it's outside.
7090  * (Use short-circuiting || so broken frames don't screw this up) */
7091  if( ( part_with_feature( vp.mount, "ROOF", true ) < 0 ) || !vp.is_available() ) {
7092  vp.inside = false;
7093  continue;
7094  }
7095 
7096  vp.inside = true; // inside if not otherwise
7097  for( const point &offset : four_adjacent_offsets ) { // let's check four neighbor parts
7098  bool cover = false; // if we aren't covered from sides, the roof at p won't save us
7099  for( const int near_idx : parts_at_relative( vp.mount + offset, true ) ) {
7100  const vehicle_part &vp_near = part( near_idx );
7101  const vpart_info &vpi_near = vp_near.info();
7102  if( !vp_near.is_available() ) {
7103  continue; // keep looking
7104  }
7105  if( vpi_near.has_flag( "ROOF" ) ) { // another roof -- cover
7106  cover = true;
7107  break;
7108  } else if( vpi_near.has_flag( "OBSTACLE" ) ) { // obstacle, like board or windshield or door
7109  if( vp_near.inside || ( vpi_near.has_flag( "OPENABLE" ) && vp_near.open ) ) {
7110  continue; // door and it's open -- can't cover
7111  }
7112  cover = true;
7113  break;
7114  }
7115  // keep looking, there might be another part in that square
7116  }
7117  if( !cover ) {
7118  vp.inside = false;
7119  break;
7120  }
7121  }
7122  }
7123 }
bool inside
if tile provides cover.
Definition: vehicle.h:500

References four_adjacent_offsets, get_all_parts(), vpart_info::has_flag(), vehicle_part::info(), vehicle_part::inside, insides_dirty, vehicle_part::is_available(), vehicle_part::mount, vehicle_part::open, part(), part_with_feature(), parts_at_relative(), and vehicle_part::removed.

Referenced by enclosed_at(), and vpart_position::is_inside().

◆ refresh_pivot()

void vehicle::refresh_pivot ( ) const
private

Definition at line 6556 of file vehicle.cpp.

6557 {
6558  // Const method, but messes with mutable fields
6559  pivot_dirty = false;
6560 
6561  if( wheelcache.empty() || !valid_wheel_config() ) {
6562  // No usable wheels, use CoM (dragging)
6564  return;
6565  }
6566 
6567  // The model here is:
6568  //
6569  // We are trying to rotate around some point (xc,yc)
6570  // This produces a friction force / moment from each wheel resisting the
6571  // rotation. We want to find the point that minimizes that resistance.
6572  //
6573  // For a given wheel w at (xw,yw), find:
6574  // weight(w): a scaling factor for the friction force based on wheel
6575  // size, brokenness, steerability/orientation
6576  // center_dist: the distance from (xw,yw) to (xc,yc)
6577  // centerline_angle: the angle between the X axis and a line through
6578  // (xw,yw) and (xc,yc)
6579  //
6580  // Decompose the force into two components, assuming that the wheel is
6581  // aligned along the X axis and we want to apply different weightings to
6582  // the in-line vs perpendicular parts of the force:
6583  //
6584  // Resistance force in line with the wheel (X axis)
6585  // Fi = weightI(w) * center_dist * sin(centerline_angle)
6586  // Resistance force perpendicular to the wheel (Y axis):
6587  // Fp = weightP(w) * center_dist * cos(centerline_angle);
6588  //
6589  // Then find the moment that these two forces would apply around (xc,yc)
6590  // moment(w) = center_dist * cos(centerline_angle) * Fi +
6591  // center_dist * sin(centerline_angle) * Fp
6592  //
6593  // Note that:
6594  // cos(centerline_angle) = (xw-xc) / center_dist
6595  // sin(centerline_angle) = (yw-yc) / center_dist
6596  // -> moment(w) = weightP(w)*(xw-xc)^2 + weightI(w)*(yw-yc)^2
6597  // = weightP(w)*xc^2 - 2*weightP(w)*xc*xw + weightP(w)*xw^2 +
6598  // weightI(w)*yc^2 - 2*weightI(w)*yc*yw + weightI(w)*yw^2
6599  //
6600  // which happily means that the X and Y axes can be handled independently.
6601  // We want to minimize sum(moment(w)) due to wheels w=0,1,..., which
6602  // occurs when:
6603  //
6604  // sum( 2*xc*weightP(w) - 2*weightP(w)*xw ) = 0
6605  // -> xc = (weightP(0)*x0 + weightP(1)*x1 + ...) /
6606  // (weightP(0) + weightP(1) + ...)
6607  // sum( 2*yc*weightI(w) - 2*weightI(w)*yw ) = 0
6608  // -> yc = (weightI(0)*y0 + weightI(1)*y1 + ...) /
6609  // (weightI(0) + weightI(1) + ...)
6610  //
6611  // so it turns into a fairly simple weighted average of the wheel positions.
6612 
6613  float xc_numerator = 0.0f;
6614  float xc_denominator = 0.0f;
6615  float yc_numerator = 0.0f;
6616  float yc_denominator = 0.0f;
6617 
6618  for( int p : wheelcache ) {
6619  const vehicle_part &wheel = parts[p];
6620 
6621  // TODO: load on tire?
6622  const int contact_area = wheel.info().wheel_info->contact_area;
6623  float weight_i; // weighting for the in-line part
6624  float weight_p; // weighting for the perpendicular part
6625  if( wheel.is_broken() ) {
6626  // broken wheels don't roll on either axis
6627  weight_i = contact_area * 2.0;
6628  weight_p = contact_area * 2.0;
6629  } else if( part_with_feature( wheel.mount, "STEERABLE", true ) != -1 ) {
6630  // Unbroken steerable wheels can handle motion on both axes
6631  // (but roll a little more easily inline)
6632  weight_i = contact_area * 0.1;
6633  weight_p = contact_area * 0.2;
6634  } else {
6635  // Regular wheels resist perpendicular motion
6636  weight_i = contact_area * 0.1;
6637  weight_p = contact_area;
6638  }
6639 
6640  xc_numerator += weight_p * wheel.mount.x;
6641  yc_numerator += weight_i * wheel.mount.y;
6642  xc_denominator += weight_p;
6643  yc_denominator += weight_i;
6644  }
6645 
6646  if( xc_denominator < 0.1 || yc_denominator < 0.1 ) {
6647  debugmsg( "vehicle::refresh_pivot had a bad weight: xc=%.3f/%.3f yc=%.3f/%.3f",
6648  xc_numerator, xc_denominator, yc_numerator, yc_denominator );
6650  } else {
6651  pivot_cache.x = std::round( xc_numerator / xc_denominator );
6652  pivot_cache.y = std::round( yc_numerator / yc_denominator );
6653  }
6654 }

References debugmsg, vehicle_part::info(), vehicle_part::is_broken(), local_center_of_mass(), vehicle_part::mount, part_with_feature(), parts, pivot_cache, pivot_dirty, round(), valid_wheel_config(), vpart_info::wheel_info, wheelcache, point::x, and point::y.

Referenced by pivot_point().

◆ refresh_zones()

bool vehicle::refresh_zones ( )

Definition at line 8258 of file vehicle.cpp.

8259 {
8260  if( zones_dirty ) {
8261  map &here = get_map();
8262  decltype( loot_zones ) new_zones;
8263  for( auto const &z : loot_zones ) {
8264  zone_data zone = z.second;
8265  //Get the global position of the first cargo part at the relative coordinate
8266 
8267  const int part_idx = part_with_feature( z.first, "CARGO", false );
8268  if( part_idx == -1 ) {
8269  debugmsg( "Could not find cargo part at %d,%d on vehicle %s for loot zone. Removing loot zone.",
8270  z.first.x, z.first.y, this->name );
8271 
8272  // If this loot zone refers to a part that no longer exists at this location, then its unattached somehow.
8273  // By continuing here and not adding to new_zones, we effectively remove it
8274  continue;
8275  }
8276  tripoint zone_pos = global_part_pos3( part_idx );
8277  zone_pos = here.getabs( zone_pos );
8278  //Set the position of the zone to that part
8279  zone.set_position( std::pair<tripoint, tripoint>( zone_pos, zone_pos ), false, false, true );
8280  new_zones.emplace( z.first, zone );
8281  }
8282  loot_zones = new_zones;
8283  zones_dirty = false;
8285  return true;
8286  }
8287  return false;
8288 }
void set_position(const std::pair< tripoint, tripoint > &position, bool manual=true, bool update_avatar=true, bool skip_cache_update=false)
Definition: clzones.cpp:668
void cache_data(bool update_avatar=true)
Definition: clzones.cpp:854

References zone_manager::cache_data(), debugmsg, zone_manager::get_manager(), get_map(), map::getabs(), global_part_pos3(), loot_zones, part_with_feature(), zone_data::set_position(), and zones_dirty.

Referenced by map::get_vehicle_zones().

◆ reload_seeds()

void vehicle::reload_seeds ( const tripoint pos)

Definition at line 878 of file vehicle_use.cpp.

879 {
880  Character &player_character = get_player_character();
881  std::vector<item *> seed_inv = player_character.cache_get_items_with( "is_seed", &item::is_seed );
882 
883  auto seed_entries = iexamine::get_seed_entries( seed_inv );
884  seed_entries.emplace( seed_entries.begin(), itype_null, _( "No seed" ), 0 );
885 
886  int seed_index = iexamine::query_seed( seed_entries );
887 
888  if( seed_index > 0 && seed_index < static_cast<int>( seed_entries.size() ) ) {
889  const int count = std::get<2>( seed_entries[seed_index] );
890  int amount = 0;
891  const std::string popupmsg = string_format( _( "Move how many? [Have %d] (0 to cancel)" ), count );
892 
893  amount = string_input_popup()
894  .title( popupmsg )
895  .width( 5 )
896  .only_digits( true )
897  .query_int();
898 
899  if( amount > 0 ) {
900  int actual_amount = std::min( amount, count );
901  itype_id seed_id = std::get<0>( seed_entries[seed_index] );
902  std::list<item> used_seed;
903  if( item::count_by_charges( seed_id ) ) {
904  used_seed = player_character.use_charges( seed_id, actual_amount );
905  } else {
906  used_seed = player_character.use_amount( seed_id, actual_amount );
907  }
908  used_seed.front().set_age( 0_turns );
909  //place seeds into the planter
910  // TODO: fix point types
911  put_into_vehicle_or_drop( player_character, item_drop_reason::deliberate, used_seed,
912  tripoint_bub_ms( pos ) );
913  }
914  }
915 }
std::vector< item * > cache_get_items_with(const itype_id &type, const std::function< bool(item &)> &do_and_check_func=return_true< item >)
Returns all items with the given flag and/or that pass the given boolean item function,...
Definition: character.cpp:9494
std::list< item > use_amount(const itype_id &it, int quantity, const std::function< bool(const item &)> &filter=return_true< item >, bool select_ind=false)
Definition: character.cpp:9595
std::list< item > use_charges(const itype_id &what, int qty, const std::function< bool(const item &)> &filter=return_true< item >)
Use charges in character inventory.
Definition: character.cpp:9769
bool is_seed() const
Whether this is actually a seed, the seed functions won't be of much use for non-seeds.
Definition: item.cpp:14201
Shows a window querying the user for input.
string_input_popup & title(const std::string &value)
The title: short string before the actual input field.
string_input_popup & width(int value)
Width (in console cells) of the input field itself.
int query_int(bool loop=true, bool draw_only=false)
string_input_popup & only_digits(bool value)
If true, any non-digit input cancels the input.
std::vector< seed_tuple > get_seed_entries(const std::vector< item * > &seed_inv)
Make lists of unique seed types and names for the menu(no multiple hemp seeds etc)
Definition: iexamine.cpp:2476
int query_seed(const std::vector< seed_tuple > &seed_entries)
Choose seed for planting.
Definition: iexamine.cpp:2502
static const itype_id itype_null("null")

References _, Character::cache_get_items_with(), item::count_by_charges(), deliberate, get_player_character(), iexamine::get_seed_entries(), item::is_seed(), itype_null, min(), string_input_popup::only_digits(), pos, put_into_vehicle_or_drop(), string_input_popup::query_int(), iexamine::query_seed(), string_format(), string_input_popup::title(), Character::use_amount(), Character::use_charges(), and string_input_popup::width().

◆ relocate_passengers()

void vehicle::relocate_passengers ( const std::vector< Character * > &  passengers) const

Definition at line 2363 of file vehicle.cpp.

2364 {
2365  const auto boardables = get_avail_parts( "BOARDABLE" );
2366  for( Character *passenger : passengers ) {
2367  for( const vpart_reference &vp : boardables ) {
2368  if( vp.part().passenger_id == passenger->getID() ) {
2369  passenger->setpos( vp.pos() );
2370  }
2371  }
2372  }
2373 }

References get_avail_parts().

Referenced by split_vehicles().

◆ remote_controlled()

bool vehicle::remote_controlled ( const Character p) const

Definition at line 274 of file vehicle.cpp.

275 {
276  vehicle *veh = g->remoteveh();
277  if( veh != this ) {
278  return false;
279  }
280 
281  for( const vpart_reference &vp : get_avail_parts( "REMOTE_CONTROLS" ) ) {
282  if( rl_dist( p.pos(), vp.pos() ) <= 40 ) {
283  return true;
284  }
285  }
286 
287  add_msg( m_bad, _( "Lost connection with the vehicle due to distance!" ) );
288  g->setremoteveh( nullptr );
289  return false;
290 }

References _, add_msg(), g, get_avail_parts(), m_bad, Creature::pos(), and rl_dist().

Referenced by map::displace_vehicle(), on_move(), and player_in_control().

◆ remove_carried_vehicle()

bool vehicle::remove_carried_vehicle ( const std::vector< int > &  carried_parts,
const std::vector< int > &  racks 
)

Definition at line 2157 of file vehicle.cpp.

2159 {
2160  if( carried_parts.empty() || racks.empty() ) {
2161  return false;
2162  }
2163  std::optional<vehicle_part::carried_part_data> carried_pivot;
2164  tripoint pivot_pos;
2165  for( int carried_part : carried_parts ) {
2166  const auto &carried_stack = parts[carried_part].carried_stack;
2167  // pivot is the stack that has zeroed mount point, only it has valid axis set
2168  if( !carried_stack.empty() && carried_stack.top().mount == tripoint_zero ) {
2169  carried_pivot = carried_stack.top();
2170  pivot_pos = global_part_pos3( carried_part );
2171  break;
2172  }
2173  }
2174  if( !carried_pivot.has_value() ) {
2175  debugmsg( "unracking failed: couldn't find pivot of carried vehicle" );
2176  return false;
2177  }
2178  units::angle new_dir = normalize( carried_pivot->face_dir + face.dir() );
2179  units::angle host_dir = normalize( face.dir(), 180_degrees );
2180  // if the host is skewed N/S, and the carried vehicle is going to come at an angle,
2181  // force it to east/west instead
2182  if( host_dir >= 45_degrees && host_dir <= 135_degrees ) {
2183  if( new_dir <= 45_degrees || new_dir >= 315_degrees ) {
2184  new_dir = 0_degrees;
2185  } else if( new_dir >= 135_degrees && new_dir <= 225_degrees ) {
2186  new_dir = 180_degrees;
2187  }
2188  }
2189  map &here = get_map();
2190  vehicle *new_vehicle = here.add_vehicle( vehicle_prototype_none, pivot_pos, new_dir );
2191  if( new_vehicle == nullptr ) {
2192  add_msg_debug( debugmode::DF_VEHICLE, "Unable to unload bike rack, host face %d, new_dir %d!",
2193  to_degrees( face.dir() ), to_degrees( new_dir ) );
2194  return false;
2195  }
2196 
2197  std::vector<point> new_mounts;
2198  new_vehicle->name = carried_pivot->veh_name;
2199  new_vehicle->owner = owner;
2200  new_vehicle->old_owner = old_owner;
2201  for( int carried_part : carried_parts ) {
2202  const vehicle_part &pt = parts[carried_part];
2203  tripoint mount;
2204  if( !pt.carried_stack.empty() ) {
2205  mount = pt.carried_stack.top().mount;
2206  } else {
2207  // FIX #28712; if we get here it means that a part was added to the bike while the latter was a carried vehicle.
2208  // This part didn't get a carry_names because those are assigned when the carried vehicle is loaded.
2209  // We can't be sure to which vehicle it really belongs to, so it will be detached from the vehicle.
2210  // We can at least inform the player that there's something wrong.
2211  add_msg( m_warning,
2212  _( "A part of the vehicle ('%s') has no containing vehicle's name. It will be detached from the %s vehicle." ),
2213  pt.name(), new_vehicle->name );
2214 
2215  // check if any other parts at the same location have a valid carry name so we can still have a valid mount location.
2216  for( const int &local_part : parts_at_relative( pt.mount, true ) ) {
2217  if( !parts[local_part].carried_stack.empty() ) {
2218  mount = parts[local_part].carried_stack.top().mount;
2219  break;
2220  }
2221  }
2222  }
2223  new_mounts.push_back( mount.xy() );
2224  }
2225 
2226  for( const int &rack_part : racks ) {
2227  parts[rack_part].remove_flag( vp_flag::carrying_flag );
2228  parts[rack_part].remove_flag( vp_flag::tracked_flag );
2229  }
2230  if( split_vehicles( here, { carried_parts }, { new_vehicle }, { new_mounts } ) ) {
2231  //~ %s is the vehicle being loaded onto the bicycle rack
2232  add_msg( _( "You unload the %s from the bike rack." ), new_vehicle->name );
2233  bool tracked_parts = false; // if any of the unracked vehicle parts carry a tracked_flag
2234  for( vehicle_part &part : new_vehicle->parts ) {
2235  tracked_parts |= part.has_flag( vp_flag::tracked_flag );
2236 
2237  if( part.carried_stack.empty() ) {
2238  // note: we get here if the part was added while the vehicle was carried / mounted.
2239  // This is not expected, still try to remove the carried flag, if any.
2240  debugmsg( "unracked vehicle part had no carried flag, this is an invalid state" );
2243  } else {
2244  part.carried_stack.pop();
2245  if( part.carried_stack.empty() ) {
2248  }
2249  }
2250  }
2251  if( tracked_parts ) {
2252  new_vehicle->toggle_tracking();
2253  }
2254  here.dirty_vehicle_list.insert( this );
2256  new_vehicle->enable_refresh();
2257  for( const int p : new_vehicle->engines ) {
2258  vehicle_part &vp = new_vehicle->parts[p];
2259  vp.enabled = !vp.is_broken();
2260  }
2261  here.invalidate_map_cache( here.get_abs_sub().z() );
2263  return true;
2264  } else {
2265  for( const int &rack_part : racks ) {
2266  parts[rack_part].set_flag( vp_flag::carrying_flag );
2267  parts[rack_part].set_flag( vp_flag::tracked_flag );
2268  }
2269  //~ %s is the vehicle being loaded onto the bicycle rack
2270  add_msg( m_bad, _( "You can't unload the %s from the bike rack." ), new_vehicle->name );
2271  return false;
2272  }
2273 }
vehicle * add_vehicle(const vproto_id &type, const tripoint &p, const units::angle &dir, int init_veh_fuel=-1, int init_veh_status=-1, bool merge_wrecks=true)
Definition: mapgen.cpp:6713
void part_removal_cleanup()
Definition: vehicle.cpp:2133
void enable_refresh()
Definition: vehicle.cpp:6148
static const vproto_id vehicle_prototype_none("none")

References _, add_msg(), add_msg_debug, map::add_vehicle(), carried_flag, vehicle_part::carried_stack, carrying_flag, debugmsg, debugmode::DF_VEHICLE, tileray::dir(), map::dirty_vehicle_list, enable_refresh(), vehicle_part::enabled, engines, face, map::get_abs_sub(), get_map(), global_part_pos3(), vehicle_part::has_flag(), map::invalidate_map_cache(), vehicle_part::is_broken(), m_bad, m_warning, vehicle_part::mount, vehicle_part::name(), name, normalize(), old_owner, owner, part(), part_removal_cleanup(), parts, parts_at_relative(), map::rebuild_vehicle_level_caches(), vehicle_part::remove_flag(), split_vehicles(), units::to_degrees(), toggle_tracking(), tracked_flag, tripoint_zero, vehicle_prototype_none, tripoint::xy(), and coords::coord_point_mut< Point, Subpoint, InBounds >::z().

Referenced by bikerack_unracking_activity_actor::finish().

◆ remove_fake_parts()

void vehicle::remove_fake_parts ( bool  cleanup = true)
private

Definition at line 6516 of file vehicle.cpp.

6517 {
6518  if( fake_parts.empty() ) {
6519  edges.clear();
6520  return;
6521  }
6522  for( const int fake_index : fake_parts ) {
6523  if( fake_index >= part_count() ) {
6524  debugmsg( "tried to remove fake part at %d but only %zu parts!", fake_index,
6525  parts.size() );
6526  continue;
6527  }
6528  vehicle_part &part_fake = parts.at( fake_index );
6529  int real_index = part_fake.fake_part_to;
6530  if( real_index >= part_count() ) {
6531  debugmsg( "tried to remove fake part at %d with real at %d but only %zu parts!",
6532  fake_index, real_index, parts.size() );
6533  } else {
6534  vehicle_part &part_real = parts.at( real_index );
6535  part_real.has_fake = false;
6536  part_real.fake_part_at = -1;
6537  }
6538  part_fake.removed = true;
6539  }
6540  edges.clear();
6541  fake_parts.clear();
6542  if( cleanup ) {
6544  }
6545 }

References debugmsg, do_remove_part_actual(), edges, vehicle_part::fake_part_at, vehicle_part::fake_part_to, fake_parts, vehicle_part::has_fake, part_count(), parts, and vehicle_part::removed.

Referenced by install_part(), merge_rackable_vehicle(), merge_vehicle_parts(), and part_removal_cleanup().

◆ remove_item() [1/2]

vehicle_stack::iterator vehicle::remove_item ( vehicle_part vp,
const vehicle_stack::const_iterator it 
)

Definition at line 5910 of file vehicle.cpp.

5912 {
5913  invalidate_mass();
5914  return vp.items.erase( it );
5915 }
iterator erase(const const_iterator &it)
Removes the element pointed to by the supplied iterator, from the colony.
Definition: colony.h:1755

References cata::colony< element_type, element_allocator_type, element_skipfield_type >::erase(), invalidate_mass(), and vehicle_part::items.

◆ remove_item() [2/2]

bool vehicle::remove_item ( vehicle_part vp,
item it 
)

Definition at line 5899 of file vehicle.cpp.

5900 {
5901  const cata::colony<item> &veh_items = vp.items;
5903  if( iter == veh_items.end() ) {
5904  return false;
5905  }
5906  remove_item( vp, iter );
5907  return true;
5908 }
iterator get_iterator_from_pointer(const pointer element_pointer) const
Getting a pointer from an iterator is simple - simply dereference it then grab the address ie.
Definition: colony.h:3120
COLONY_FORCE_INLINE iterator end() noexcept
Definition: colony.h:841
bool remove_item(vehicle_part &vp, item *it)
Definition: vehicle.cpp:5899

References cata::colony< element_type, element_allocator_type, element_skipfield_type >::end(), cata::colony< element_type, element_allocator_type, element_skipfield_type >::get_iterator_from_pointer(), and vehicle_part::items.

Referenced by unload_loot_activity_actor::do_turn(), vehicle_stack::erase(), and move_item().

◆ remove_old_owner()

void vehicle::remove_old_owner ( )
inline

Definition at line 969 of file vehicle.h.

969  {
970  theft_time = std::nullopt;
972  }

References string_id< faction >::NULL_ID(), old_owner, and theft_time.

Referenced by handle_potential_theft().

◆ remove_part() [1/2]

bool vehicle::remove_part ( vehicle_part vp)

Mark a part as removed from the vehicle.

Parameters
handlerA class that receives various callbacks, e.g. for placing items. This handler is different when called during mapgen (when items need to be placed on the temporary mapgen map), and when called during normal game play (when items go on the main map g->m).
Returns
bool true if the vehicle's 0,0 point shifted.

Definition at line 1966 of file vehicle.cpp.

1967 {
1968  DefaultRemovePartHandler handler;
1969  return remove_part( vp, handler );
1970 }

Referenced by break_off(), veh_interact::complete_vehicle(), damage_direct(), invalidate_towing(), item_location::impl::item_on_vehicle::remove_item(), remove_part(), veh_utils::repair_part(), shed_loose_parts(), smash(), and unlink_cables().

◆ remove_part() [2/2]

bool vehicle::remove_part ( vehicle_part vp,
RemovePartHandler handler 
)

Definition at line 1972 of file vehicle.cpp.

1973 {
1974  // NOTE: Don't access g or g->m or anything from it directly here.
1975  // Forward all access to the handler.
1976  // There are currently two implementations of it:
1977  // - one for normal game play (vehicle is on the main map g->m),
1978  // - one for mapgen (vehicle is on a temporary map used only during mapgen).
1979  const vpart_info &vpi = vp.info();
1980  if( vp.removed ) {
1981  /* This happens only when we had to remove part, because it was depending on
1982  * other part (using recursive remove_part() call) - currently curtain
1983  * depending on presence of window and seatbelt depending on presence of seat.
1984  */
1985  return false;
1986  }
1987 
1988  const tripoint part_loc = global_part_pos3( vp );
1989 
1990  if( !handler.get_map_ref().inbounds( part_loc ) ) {
1991  debugmsg( "vehicle::remove_part part '%s' at mount %s bub pos %s is out of map "
1992  "bounds on vehicle '%s'(%s), vehicle::pos is %s, vehicle::sm_pos is %s",
1993  vpi.id.str(), vp.mount.to_string(), part_loc.to_string(),
1994  name, type.str(), pos.to_string(), sm_pos.to_string() );
1995  }
1996 
1997  // Unboard any entities standing on removed boardable parts
1998  if( vpi.has_flag( "BOARDABLE" ) && vp.has_flag( vp_flag::passenger_flag ) ) {
1999  handler.unboard( part_loc );
2000  }
2001 
2002  for( const item &it : vp.tools ) {
2003  handler.add_item_or_charges( part_loc, it, false );
2004  }
2005 
2006  // If `p` has flag `parent_flag`, remove child with flag `child_flag`
2007  // Returns true if removal occurs
2008  const auto remove_dependent_part = [&](
2009  const std::string & parent_flag, const std::string & child_flag ) {
2010  const int dep = part_with_feature( vp.mount, child_flag, false );
2011  if( magic || ( dep < 0 ) || !vpi.has_flag( parent_flag ) ) {
2012  return false;
2013  }
2014  vehicle_part &vp_dep = parts[dep];
2015  handler.add_item_or_charges( part_loc, part_to_item( vp_dep ), false );
2016  remove_part( vp_dep, handler );
2017  return true;
2018  };
2019 
2020  // if a windshield is removed (usually destroyed) also remove curtains
2021  // attached to it.
2022  if( remove_dependent_part( "WINDOW", "CURTAIN" ) || vpi.has_flag( VPFLAG_OPAQUE ) ) {
2024  }
2025 
2026  if( vpi.has_flag( VPFLAG_ROOF ) || vpi.has_flag( VPFLAG_OPAQUE ) ) {
2027  handler.set_floor_cache_dirty( sm_pos.z + 1 );
2028  }
2029 
2030  remove_dependent_part( "SEAT", "SEATBELT" );
2031  remove_dependent_part( "BATTERY_MOUNT", "NEEDS_BATTERY_MOUNT" );
2032  remove_dependent_part( "HANDHELD_BATTERY_MOUNT", "NEEDS_HANDHELD_BATTERY_MOUNT" );
2033 
2034  // Release any animal held by the part
2035  if( vp.has_flag( vp_flag::animal_flag ) ) {
2036  item base = vp.get_base();
2037  handler.spawn_animal_from_part( base, part_loc );
2038  vp.set_base( std::move( base ) );
2040  }
2041 
2042  // Update current engine configuration if needed
2043  if( vpi.has_flag( VPFLAG_ENGINE ) && engines.size() > 1 ) {
2044  bool any_engine_on = false;
2045 
2046  for( const int e : engines ) {
2047  const vehicle_part &vp_engine = parts[e];
2048  if( &vp != &vp_engine && vp_engine.enabled ) {
2049  any_engine_on = true;
2050  break;
2051  }
2052  }
2053 
2054  if( !any_engine_on ) {
2055  engine_on = false;
2056  for( const int e : engines ) {
2057  vehicle_part &vp_engine = parts[e];
2058  vp_engine.enabled = true;
2059  }
2060  }
2061  }
2062 
2063  //Remove loot zone if Cargo was removed.
2064  const auto lz_iter = loot_zones.find( vp.mount );
2065  const bool no_zone = lz_iter != loot_zones.end();
2066 
2067  if( no_zone && vpi.has_flag( VPFLAG_CARGO ) ) {
2068  // Using the key here (instead of the iterator) will remove all zones on
2069  // this mount points regardless of how many there are
2070  loot_zones.erase( vp.mount );
2071  zones_dirty = true;
2072  }
2073  vp.removed = true;
2074  if( vp.has_fake && vp.fake_part_at < static_cast<int>( parts.size() ) ) {
2075  parts[vp.fake_part_at].removed = true;
2076  }
2077 
2078  const int vp_idx = index_of_part( &vp, /* include_removed = */ true );
2079  handler.removed( *this, vp_idx );
2080 
2081  const point &vp_mount = vp.mount;
2082  const auto iter = labels.find( label( vp_mount ) );
2083  if( iter != labels.end() && parts_at_relative( vp_mount, false ).empty() ) {
2084  labels.erase( iter );
2085  }
2086 
2087  for( item &i : get_items( vp ) ) {
2088  // Note: this can spawn items on the other side of the wall!
2089  // TODO: fix this ^^
2090  if( !magic ) {
2091  tripoint dest( part_loc + point( rng( -3, 3 ), rng( -3, 3 ) ) );
2092  // This new point might be out of the map bounds. It's not
2093  // reasonable to try to spawn it outside the currently valid map,
2094  // so we pass true here to cause such points to be clamped to the
2095  // valid bounds without printing an error (as would normally
2096  // occur).
2097  handler.add_item_or_charges( dest, i, true );
2098  }
2099  }
2100  refresh( false );
2101  coeff_air_changed = true;
2102  return shift_if_needed( handler.get_map_ref() );
2103 }
virtual void set_transparency_cache_dirty(int z)=0
virtual void spawn_animal_from_part(item &base, const tripoint &loc)=0
virtual map & get_map_ref()=0
virtual void removed(vehicle &veh, int part)=0
virtual void set_floor_cache_dirty(int z)=0
virtual void add_item_or_charges(const tripoint &loc, item it, bool permit_oob)=0
virtual void unboard(const tripoint &loc)=0
std::string label(item const &it, unsigned int quantity, segment_bitset const &segments)
Definition: item_tname.cpp:142
std::string to_string() const
Definition: point.cpp:51
const item & get_base() const
void set_base(item &&new_base)
@ VPFLAG_ROOF
Definition: veh_type.h:110

References RemovePartHandler::add_item_or_charges(), animal_flag, coeff_air_changed, debugmsg, vehicle_part::enabled, engine_on, engines, vehicle_part::fake_part_at, vehicle_part::get_base(), get_items(), RemovePartHandler::get_map_ref(), global_part_pos3(), vehicle_part::has_fake, vpart_info::has_flag(), vehicle_part::has_flag(), vpart_info::id, map::inbounds(), index_of_part(), vehicle_part::info(), anonymous_namespace{item_tname.cpp}::label(), labels, loot_zones, magic, vehicle_part::mount, name, part_to_item(), part_with_feature(), parts, parts_at_relative(), passenger_flag, point, pos, refresh(), vehicle_part::remove_flag(), remove_part(), vehicle_part::removed, RemovePartHandler::removed(), rng(), vehicle_part::set_base(), RemovePartHandler::set_floor_cache_dirty(), RemovePartHandler::set_transparency_cache_dirty(), shift_if_needed(), sm_pos, RemovePartHandler::spawn_animal_from_part(), string_id< T >::str(), point::to_string(), tripoint::to_string(), vehicle_part::tools, type, RemovePartHandler::unboard(), VPFLAG_CARGO, VPFLAG_ENGINE, VPFLAG_OPAQUE, VPFLAG_ROOF, tripoint::z, and zones_dirty.

◆ remove_remote_part()

void vehicle::remove_remote_part ( const vehicle_part vp_local) const

Remove the part on a targeted remote vehicle that a part is targeting.

Definition at line 6966 of file vehicle.cpp.

6967 {
6968  const auto part = get_remote_part( vp_local );
6969  if( part ) {
6970  part->vehicle().remove_part( part->part() );
6971  // Rebuild vehicle cache to avoid creating an illusion of the remote car.
6973  }
6974 }
friend vehicle
Definition: vehicle.h:255

References get_map(), get_remote_part(), part(), map::rebuild_vehicle_level_caches(), and vehicle_part::vehicle.

Referenced by break_off(), veh_interact::complete_vehicle(), damage_direct(), merge_vehicle_parts(), shed_loose_parts(), and unlink_cables().

◆ removed_part()

item vehicle::removed_part ( const vehicle_part vp) const

If the vehicle part has an item it is removed as, transform the item to the item it is removed_as.

Definition at line 8249 of file vehicle.cpp.

8250 {
8251  item ret = part_to_item( vp );
8252  if( vp.info().removed_item ) {
8253  ret.convert( *vp.info().removed_item );
8254  }
8255  return ret;
8256 }
std::optional< itype_id > removed_item
item it should be removed as
Definition: veh_type.h:403

References vehicle_part::info(), part_to_item(), vpart_info::removed_item, and cata::hash64_detail::ret.

Referenced by veh_interact::complete_vehicle().

◆ restore_folded_parts()

bool vehicle::restore_folded_parts ( const item it)

Definition at line 7672 of file vehicle.cpp.

7673 {
7674  const JsonValue jv_parts = json_loader::from_string( it.get_var( "folded_parts" ) );
7675  deserialize_parts( static_cast<JsonArray>( jv_parts ) );
7676 
7677  // item should have snapshot of average part damage in item var. take difference of current
7678  // item's damage and snapshotted damage, then randomly apply to parts in chunks to roughly match.
7679  constexpr int chunk_damage = 400;
7680  const int avg_part_damage = static_cast<int>( it.get_var( "avg_part_damage", 0.0 ) );
7681  const int damage_diff = it.damage() - avg_part_damage;
7682  int damage_to_apply = damage_diff * parts.size();
7683  if( damage_to_apply > 0 ) {
7685  "unfolding vehicle item with %d damage, damage before folding was %d, "
7686  "applying %d damage * %d parts = %d total damage to random parts",
7687  it.damage(), avg_part_damage, damage_diff, parts.size(), damage_to_apply );
7688  std::vector<int> part_sequence;
7689  int no_damage_applied = 0; // safety from infinite loop (e.g. all parts with flag_UNBREAKABLE)
7690  while( damage_to_apply > 0 && ( ++no_damage_applied < 100 ) ) {
7691  if( part_sequence.empty() ) {
7692  part_sequence = rng_sequence( 16, 0, parts.size() - 1, damage_to_apply );
7693  }
7694  const int part_idx = part_sequence.back();
7695  part_sequence.pop_back();
7696  if( part_idx > part_count() ) {
7697  continue;
7698  }
7699  vehicle_part &pt = parts[part_idx];
7700  if( pt.removed || pt.is_fake ) {
7701  continue;
7702  }
7703  const int start_damage = pt.base.damage();
7704  pt.base.mod_damage( std::min( chunk_damage, damage_to_apply ) );
7705  const int applied_damage = pt.base.damage() - start_damage;
7706  if( applied_damage > 0 ) {
7707  no_damage_applied = 0;
7708  damage_to_apply -= applied_damage;
7709  add_msg_debug( debugmode::DF_VEHICLE, "unfolding applied %d damage to %s %d left to apply",
7710  applied_damage, pt.name(), damage_to_apply );
7711  }
7712  }
7713  }
7714 
7715  refresh();
7716  face.init( 0_degrees );
7717  turn_dir = 0_degrees;
7718  turn( 0_degrees );
7722  return true;
7723 }
double get_var(const std::string &name, double default_value) const
Definition: item.cpp:1839
static JsonValue from_string(std::string const &data) noexcept(false)
std::vector< int > rng_sequence(size_t count, int lo, int hi, int seed)
Definition: rng.cpp:160

References add_msg_debug, vehicle_part::base, item::damage(), deserialize_parts(), debugmode::DF_VEHICLE, face, json_loader::from_string(), item::get_var(), tileray::init(), vehicle_part::is_fake, last_update, min(), item::mod_damage(), vehicle_part::name(), part_count(), parts, pivot_anchor, pivot_rotation, precalc_mounts(), refresh(), vehicle_part::removed, rng_sequence(), calendar::turn, turn(), and turn_dir.

Referenced by vehicle_unfolding_activity_actor::unfold_vehicle().

◆ roof_at_part()

int vehicle::roof_at_part ( int  p) const

Definition at line 3290 of file vehicle.cpp.

3291 {
3292  for( const int p : parts_at_relative( parts[part].mount, true ) ) {
3293  const vehicle_part &vp = parts[p];
3294  if( vp.info().location == "on_roof" || vp.info().has_flag( VPFLAG_ROOF ) ) {
3295  return p;
3296  }
3297  }
3298  return -1;
3299 }

References vpart_info::has_flag(), vehicle_part::info(), vpart_info::location, part(), parts, parts_at_relative(), and VPFLAG_ROOF.

Referenced by map::draw_from_above(), and map::valid_move().

◆ rotated_center_of_mass()

const point & vehicle::rotated_center_of_mass ( ) const

Definition at line 3484 of file vehicle.cpp.

3485 {
3486  // TODO: Bring back caching of this point
3487  calc_mass_center( true );
3488 
3489  return mass_center_precalc;
3490 }

References calc_mass_center(), and mass_center_precalc.

Referenced by map::vehicle_vehicle_collision().

◆ rotor_acceleration()

int vehicle::rotor_acceleration ( bool  fueled = true,
int  at_vel_in_vmi = -1 
) const

Definition at line 3773 of file vehicle.cpp.

3774 {
3775  ( void )at_vel_in_vmi;
3776  if( !( engine_on || is_flying ) ) {
3777  return 0;
3778  }
3779  const int accel_at_vel = 100 * lift_thrust_of_rotorcraft( fueled ) / to_kilogram( total_mass() );
3780  return cmps_to_vmiph( accel_at_vel );
3781 }

References cmps_to_vmiph(), engine_on, is_flying, lift_thrust_of_rotorcraft(), units::to_kilogram(), and total_mass().

Referenced by acceleration(), and veh_interact::display_stats().

◆ safe_ground_velocity()

int vehicle::safe_ground_velocity ( bool  fueled = true) const

Definition at line 3946 of file vehicle.cpp.

3947 {
3948  int effective_engine_w = units::to_watt( total_power( fueled, true ) );
3949  double c_rolling_drag = coeff_rolling_drag();
3950  double safe_in_mps = simple_cubic_solution( coeff_air_drag(), c_rolling_drag,
3951  c_rolling_drag * vehicles::rolling_constant_to_variable,
3952  -effective_engine_w );
3953  return mps_to_vmiph( safe_in_mps );
3954 }

References coeff_air_drag(), coeff_rolling_drag(), mps_to_vmiph(), vehicles::rolling_constant_to_variable, simple_cubic_solution(), units::to_watt(), and total_power().

Referenced by veh_interact::display_stats(), safe_velocity(), and smart_controller_handle_turn().

◆ safe_rotor_velocity()

int vehicle::safe_rotor_velocity ( bool  fueled = true) const

Definition at line 3956 of file vehicle.cpp.

3957 {
3958  const double max_air_mps = std::sqrt( lift_thrust_of_rotorcraft( fueled,
3959  true ) / coeff_air_drag() );
3960  return std::min( 22501, mps_to_vmiph( max_air_mps ) );
3961 }

References coeff_air_drag(), lift_thrust_of_rotorcraft(), min(), mps_to_vmiph(), and sqrt().

Referenced by veh_interact::display_stats(), and safe_velocity().

◆ safe_velocity()

int vehicle::safe_velocity ( bool  fueled = true) const

Definition at line 3972 of file vehicle.cpp.

3973 {
3974  if( is_flying && is_rotorcraft() ) {
3975  return safe_rotor_velocity( fueled );
3976  } else if( is_watercraft() ) {
3977  return safe_water_velocity( fueled );
3978  } else {
3979  return safe_ground_velocity( fueled );
3980  }
3981 }
int safe_ground_velocity(bool fueled=true) const
Definition: vehicle.cpp:3946
int safe_rotor_velocity(bool fueled=true) const
Definition: vehicle.cpp:3956
int safe_water_velocity(bool fueled=true) const
Definition: vehicle.cpp:3964

References is_flying, is_rotorcraft(), is_watercraft(), safe_ground_velocity(), safe_rotor_velocity(), and safe_water_velocity().

Referenced by control_engines(), cruise_thrust(), drive_to_local_target(), and strain().

◆ safe_water_velocity()

int vehicle::safe_water_velocity ( bool  fueled = true) const

Definition at line 3964 of file vehicle.cpp.

3965 {
3966  int total_engine_w = units::to_watt( total_power( fueled, true ) );
3967  double total_drag = coeff_water_drag() + coeff_air_drag();
3968  double safe_in_mps = std::cbrt( total_engine_w / total_drag );
3969  return mps_to_vmiph( safe_in_mps );
3970 }

References coeff_air_drag(), coeff_water_drag(), mps_to_vmiph(), units::to_watt(), and total_power().

Referenced by veh_interact::display_stats(), and safe_velocity().

◆ search_connected_batteries()

std::map< vpart_reference, float > vehicle::search_connected_batteries ( )

Returns a map of connected battery references to power loss factor Keys are batteries in vehicles (includes self) connected by POWER_TRANSFER parts Values are line loss, 0.01 corresponds to 1% charge loss to wire resistance May load the connected vehicles' submaps.

Definition at line 5442 of file vehicle.cpp.

5443 {
5444  std::map<vpart_reference, float> result;
5445 
5446  for( const std::pair<vehicle *const, float> &pair : search_connected_vehicles() ) {
5447  vehicle *veh = pair.first;
5448  const float efficiency = pair.second;
5449  for( const int part_idx : veh->batteries ) {
5450  const vpart_reference vpr( *veh, part_idx );
5451  if( vpr.part().is_fake ) {
5452  continue;
5453  }
5454  result.emplace( vpr, efficiency );
5455  }
5456  }
5457 
5458  return result;
5459 }

References batteries, vehicle_part::is_fake, vpart_reference::part(), and search_connected_vehicles().

Referenced by charge_battery(), discharge_battery(), and has_battery_in_grid().

◆ search_connected_vehicles() [1/3]

std::map< vehicle *, float > vehicle::search_connected_vehicles ( )

Returns a map of connected vehicle pointers to power loss factor: Keys are vehicles connected by POWER_TRANSFER parts, includes self Values are line loss, 0.01 corresponds to 1% charge loss to wire resistance May load the connected vehicles' submaps Templated to support const and non-const vehicle*.

Definition at line 5413 of file vehicle.cpp.

5414 {
5415  return search_connected_vehicles( this );
5416 }

Referenced by battery_left(), connected_battery_power_level(), fuel_capacity(), fuel_left(), search_connected_batteries(), and search_connected_vehicles().

◆ search_connected_vehicles() [2/3]

std::map< const vehicle *, float > vehicle::search_connected_vehicles ( ) const

Returns a map of connected vehicle pointers to power loss factor: Keys are vehicles connected by POWER_TRANSFER parts, includes self Values are line loss, 0.01 corresponds to 1% charge loss to wire resistance May load the connected vehicles' submaps Templated to support const and non-const vehicle*.

Definition at line 5418 of file vehicle.cpp.

5419 {
5420  return search_connected_vehicles( this );
5421 }

References search_connected_vehicles().

◆ search_connected_vehicles() [3/3]

template<typename Vehicle >
std::map< Vehicle *, float > vehicle::search_connected_vehicles ( Vehicle *  start)
staticprivate

Returns a map of connected vehicle pointers to power loss factor: Keys are vehicles connected by POWER_TRANSFER parts, includes self Values are line loss, 0.01 corresponds to 1% charge loss to wire resistance May load the connected vehicles' submaps Templated to support const and non-const vehicle*.

Definition at line 5372 of file vehicle.cpp.

5373 {
5374  std::map<Vehicle *, float> distances; // distance represents sum of cable losses
5375  std::vector<Vehicle *> queue;
5376 
5377  distances[start] = 0;
5378  queue.emplace_back( start );
5379  constexpr float infinity_distance = 10000.0f; // should be enough to represent "infinity"
5380 
5381  // Run dijkstra to get shortest distance tree of paths
5382  // Tree will span from self(root) to other connected vehicles
5383  // where distance metric is power transfer loss ( resistance to heat inefficiency )
5384  while( !queue.empty() ) {
5385  Vehicle *const veh = queue.back();
5386  queue.pop_back();
5387 
5388  for( const int part_idx : veh->loose_parts ) { // graph "edges" are POWER_TRANSFER parts
5389  const vehicle_part &vp = veh->part( part_idx );
5390  const vpart_info &vpi = vp.info();
5391  if( !vpi.has_flag( VPFLAG_POWER_TRANSFER ) ) {
5392  continue;
5393  }
5394 
5395  Vehicle *const v_next = find_vehicle( tripoint_abs_ms( vp.target.second ) );
5396  if( v_next == nullptr ) { // vehicle's rolled away or off-map
5397  continue;
5398  }
5399  // try insert infinity for initial unvisited node distance
5400  distances.insert( { v_next, infinity_distance } );
5401 
5402  const float loss = units::to_kilowatt<float>( vpi.epower ) / 100.0f;
5403  const float new_dist = loss + distances[veh];
5404  if( distances[v_next] > new_dist ) {
5405  distances[v_next] = new_dist;
5406  queue.emplace_back( v_next );
5407  }
5408  }
5409  }
5410  return distances;
5411 }

References vpart_info::epower, find_vehicle(), vpart_info::has_flag(), vehicle_part::info(), vehicle_part::target, and VPFLAG_POWER_TRANSFER.

Referenced by veh_app_interact::draw_info().

◆ selfdrive()

void vehicle::selfdrive ( const point p)

vehicle is driving itself

Definition at line 1307 of file vehicle_move.cpp.

1308 {
1309  if( !is_towed() && !magic && !get_harnessed_animal() && !has_part( "AUTOPILOT" ) ) {
1310  is_following = false;
1311  return;
1312  }
1313  if( p.x != 0 ) {
1314  if( steering_effectiveness() <= 0 ) {
1315  return; // no steering
1316  }
1318  }
1319  if( p.y != 0 ) {
1320  if( !is_towed() ) {
1321  const int thr_amount = std::abs( velocity ) < 2000 ? 400 : 500;
1322  cruise_thrust( -p.y * thr_amount );
1323  } else {
1324  thrust( -p.y );
1325  }
1326  }
1327  // TODO: Actually check if we're on land on water (or disable water-skidding)
1328  if( skidding && valid_wheel_config() ) {
1329  const float handling_diff = handling_difficulty();
1330  if( handling_diff * rng( 1, 10 ) < 15 ) {
1331  velocity = static_cast<int>( forward_velocity() );
1332  skidding = false;
1333  move.init( turn_dir );
1334  }
1335  }
1336 }

References abs(), cruise_thrust(), forward_velocity(), get_harnessed_animal(), handling_difficulty(), has_part(), tileray::init(), is_following, is_towed(), magic, move, rng(), skidding, vehicles::steer_increment, steering_effectiveness(), thrust(), turn(), turn_dir, valid_wheel_config(), velocity, point::x, and point::y.

Referenced by do_towing_move(), and drive_to_local_target().

◆ separate_from_grid()

void vehicle::separate_from_grid ( point  mount)

Definition at line 1912 of file vehicle.cpp.

1913 {
1914  // Disconnect items and power cords
1915  unlink_cables( mount, get_player_character(), true, true, true );
1917  if( part_count() <= 1 ) {
1918  // No need to split the power grid up.
1919  return;
1920  }
1921 
1922  // Split the target part away from the power grid.
1923  const int idx = part_displayed_at( mount, true );
1924  if( idx == -1 ) {
1925  debugmsg( "no part at mount point %s", mount.to_string() );
1926  return;
1927  }
1928  map &here = get_map();
1929  const std::string part_name = part( idx ).name();
1930  std::vector<std::vector<int>> split_indices( { { idx } } );
1931  const std::vector<vehicle *> null_vehicles( 2, nullptr );
1932  const std::vector<std::vector<point>> null_mounts( 2, std::vector<point>() );
1933  if( !split_vehicles( here, split_indices, null_vehicles, null_mounts ) ) {
1934  debugmsg( "unable to split %s from power grid", part( idx ).name( false ) );
1935  return;
1936  }
1937 
1938  // Split again if removing the target part separated the power grid into multiple sections.
1939  find_and_split_vehicles( here, {} );
1940 
1941  // Ensure the position, pivot, and precalc points are up-to-date.
1942  shift_if_needed( get_map() );
1943  pos -= pivot_anchor[0];
1944  precalc_mounts( 0, turn_dir, point() );
1945 
1946  add_msg( _( "You separate the %s from the power grid" ), part_name );
1947 
1950 }

References _, add_msg(), debugmsg, find_and_split_vehicles(), get_map(), get_player_character(), vehicle_part::name(), name, part(), part_count(), part_displayed_at(), part_removal_cleanup(), pivot_anchor, point, pos, precalc_mounts(), map::rebuild_vehicle_level_caches(), shift_if_needed(), split_vehicles(), point::to_string(), turn_dir, and unlink_cables().

Referenced by veh_app_interact::disconnect().

◆ serialize()

void vehicle::serialize ( JsonOut json) const

Definition at line 3481 of file savegame_json.cpp.

3482 {
3483  json.start_object();
3484  json.member( "type", type );
3485  json.member( "posx", pos.x );
3486  json.member( "posy", pos.y );
3487  json.member( "om_id", om_id );
3488  json.member( "faceDir", std::lround( to_degrees( face.dir() ) ) );
3489  json.member( "moveDir", std::lround( to_degrees( move.dir() ) ) );
3490  json.member( "turn_dir", std::lround( to_degrees( turn_dir ) ) );
3491  json.member( "last_turn", std::lround( to_degrees( last_turn ) ) );
3492  json.member( "velocity", velocity );
3493  json.member( "avg_velocity", avg_velocity );
3494  json.member( "falling", is_falling );
3495  json.member( "in_water", in_water );
3496  json.member( "in_deep_water", in_deep_water );
3497  json.member( "flying", is_flying );
3498  json.member( "cruise_velocity", cruise_velocity );
3499  json.member( "vertical_velocity", vertical_velocity );
3500  json.member( "engine_on", engine_on );
3501  json.member( "tracking_on", tracking_on );
3502  json.member( "skidding", skidding );
3503  json.member( "of_turn_carry", of_turn_carry );
3504  json.member( "name", name );
3505  json.member( "owner", owner );
3506  json.member( "old_owner", old_owner );
3507  json.member( "theft_time", theft_time );
3508  json.member( "parts", real_parts() );
3509  json.member( "tags", tags );
3510  json.member( "fuel_remainder", fuel_remainder );
3511  json.member( "fuel_used_last_turn", fuel_used_last_turn );
3512  json.member( "labels", labels );
3513  json.member( "zones" );
3514  json.start_array();
3515  for( auto const &z : loot_zones ) {
3516  json.start_object();
3517  json.member( "point", z.first );
3518  json.member( "zone", z.second );
3519  json.end_object();
3520  }
3521  json.end_array();
3522  tripoint other_tow_temp_point;
3523  if( is_towed() ) {
3524  vehicle *tower = tow_data.get_towed_by();
3525  if( tower ) {
3526  other_tow_temp_point = tower->global_part_pos3( tower->get_tow_part() );
3527  }
3528  }
3529  json.member( "other_tow_point", other_tow_temp_point );
3530 
3531  json.member( "is_locked", is_locked );
3532  json.member( "is_alarm_on", is_alarm_on );
3533  json.member( "camera_on", camera_on );
3534  json.member( "autopilot_on", autopilot_on );
3535  json.member( "precollision_on", precollision_on );
3536  json.member( "last_update_turn", last_update );
3537  json.member( "pivot", pivot_anchor[0] );
3538  json.member( "is_on_ramp", is_on_ramp );
3539  json.member( "is_autodriving", is_autodriving );
3540  json.member( "is_following", is_following );
3541  json.member( "is_patrolling", is_patrolling );
3542  json.member( "autodrive_local_target", autodrive_local_target );
3543  json.member( "airworthy", flyable );
3544  json.member( "requested_z_change", requested_z_change );
3545  json.member( "summon_time_limit", summon_time_limit );
3546  json.member( "magic", magic );
3547  json.member( "smart_controller", smart_controller_cfg );
3548  json.member( "vehicle_noise", vehicle_noise );
3549 
3550  json.end_object();
3551 }
void end_array()
Definition: json.cpp:2346
void start_array(bool wrap=false)
Definition: json.cpp:2335
void start_object(bool wrap=false)
Definition: json.cpp:2316
void end_object()
Definition: json.cpp:2327
void member(std::string_view name)
Definition: json.cpp:2422

References JsonOut::end_array(), JsonOut::end_object(), get_tow_part(), global_part_pos3(), JsonOut::member(), move, om_direction::name(), math_opers::pos(), JsonOut::start_array(), JsonOut::start_object(), anonymous_namespace{item_tname.cpp}::tags(), units::to_degrees(), and type.

◆ set_flyable()

void vehicle::set_flyable ( bool  val)

Definition at line 4402 of file vehicle.cpp.

4403 {
4404  flyable = val;
4405 }

References flyable.

Referenced by damage_direct(), veh_interact::do_install(), veh_interact::do_remove(), and veh_interact::do_repair().

◆ set_flying()

void vehicle::set_flying ( bool  new_flying_value)

Definition at line 4452 of file vehicle.cpp.

4453 {
4454  is_flying = new_flying_value;
4455 }

References is_flying.

◆ set_hp()

void vehicle::set_hp ( vehicle_part pt,
int  qty,
bool  keep_degradation,
int  new_degradation = -1 
)

Set stat for part constrained by range [0,durability].

Note
does not invoke base item::on_damage callback

Definition at line 628 of file vehicle_part.cpp.

629 {
630  int dur = pt.info().durability;
631  if( qty == dur || dur <= 0 ) {
632  pt.base.set_damage( keep_degradation ? pt.base.degradation() : 0 );
633 
634  } else if( qty == 0 ) {
635  pt.base.set_damage( pt.base.max_damage() );
636 
637  } else {
638  int amt = pt.base.max_damage() - pt.base.max_damage() * qty / dur;
639  amt = std::max( amt, pt.base.degradation() );
640  pt.base.set_damage( amt );
641  }
642  if( !keep_degradation ) {
643  if( new_degradation >= 0 ) {
644  pt.base.set_degradation( new_degradation );
645  } else {
646  pt.base.rand_degradation();
647  }
648  } else if( new_degradation >= 0 ) {
649  pt.base.set_degradation( new_degradation );
650  }
651 }
int degradation() const
How much degradation has the item accumulated?
Definition: item.cpp:863
void rand_degradation()
Definition: item.cpp:868

References vehicle_part::base, item::degradation(), dur, vpart_info::durability, vehicle_part::info(), max(), item::max_damage(), item::rand_degradation(), item::set_damage(), and item::set_degradation().

Referenced by init_state(), and veh_utils::repair_part().

◆ set_old_owner()

void vehicle::set_old_owner ( const faction_id temp_owner)
inline

Definition at line 965 of file vehicle.h.

965  {
967  old_owner = temp_owner;
968  }

References old_owner, theft_time, and calendar::turn.

Referenced by handle_potential_theft().

◆ set_owner() [1/2]

void vehicle::set_owner ( const Character c)

Definition at line 4677 of file vehicle.cpp.

4678 {
4679  if( !c.get_faction() ) {
4680  debugmsg( "vehicle::set_owner() player %s has no valid faction", c.disp_name() );
4681  return;
4682  }
4683  owner = c.get_faction()->id;
4684 }

References c, debugmsg, and owner.

◆ set_owner() [2/2]

void vehicle::set_owner ( const faction_id new_owner)
inline

Definition at line 973 of file vehicle.h.

973  {
974  owner = new_owner;
975  }

References owner.

Referenced by jmapgen_vehicle::apply(), map::apply_faction_ownership(), handle_potential_theft(), and vehicle_unfolding_activity_actor::unfold_vehicle().

◆ set_submap_moved()

void vehicle::set_submap_moved ( const tripoint p)

Update the submap coordinates and update the tracker info in the overmap (if enabled).

This should be called only when the vehicle has actually been moved, not when the map is just shifted (in the later case simply set smx/smy directly).

Definition at line 3462 of file vehicle.cpp.

3463 {
3464  const point_abs_ms old_msp = global_square_location().xy();
3465  sm_pos = p;
3466  if( !tracking_on ) {
3467  return;
3468  }
3469  overmap_buffer.move_vehicle( this, old_msp );
3470 }
void move_vehicle(vehicle *veh, const point_abs_ms &old_msp)
Move the tracking mark of the given vehicle.
overmapbuffer overmap_buffer

References global_square_location(), overmapbuffer::move_vehicle(), overmap_buffer, sm_pos, tracking_on, and coords::coord_point< Point, Origin, Scale, InBounds >::xy().

Referenced by map::displace_vehicle().

◆ set_tow_directions()

void vehicle::set_tow_directions ( )

Definition at line 6795 of file vehicle.cpp.

6796 {
6797  const int length = mount_max.x - mount_min.x + 1;
6798  const point mount_of_tow = parts[get_tow_part()].mount;
6799  const point normalized_tow_mount = point( std::abs( mount_of_tow.x - mount_min.x ),
6800  std::abs( mount_of_tow.y - mount_min.y ) );
6801  if( length >= 3 ) {
6802  const int trisect = length / 3;
6803  if( normalized_tow_mount.x <= trisect ) {
6805  } else if( normalized_tow_mount.x > trisect && normalized_tow_mount.x <= trisect * 2 ) {
6807  } else {
6809  }
6810  } else {
6811  // its a small vehicle, no danger if it flips around.
6813  }
6814 }
@ TOW_SIDE
Definition: vehicle.h:188

References abs(), get_tow_part(), length, mount_max, mount_min, parts, point, TOW_BACK, tow_data, towing_data::tow_direction, TOW_FRONT, TOW_SIDE, point::x, and point::y.

Referenced by towing_data::set_towing().

◆ shed_loose_parts()

void vehicle::shed_loose_parts ( trinary  shed_cables = trinary::NONE,
const tripoint_bub_ms dst = nullptr 
)

Drop parts with UNMOUNT_ON_MOVE onto the ground.

Parameters
shed_cablesIf cable parts should also be dropped.
-If set to trinary::NONE, the default, don't drop any cables.
-If set to trinary::SOME, calculate cable length, updating remote parts, and drop if it's too long.
-If set to trinary::ALL, drop all cables.
dstFuture vehicle position, used for calculating cable length when shed_cables == trinary::SOME.

Definition at line 6976 of file vehicle.cpp.

6977 {
6978  map &here = get_map();
6979  // remove_part rebuilds the loose_parts vector, so iterate over a copy to preserve
6980  // power transfer lines that still have some slack to them
6981  std::vector<int> lp = loose_parts;
6982  for( const int elem : lp ) {
6983  vehicle_part &vp_loose = part( elem );
6984  const vpart_info &vpi_loose = vp_loose.info();
6985  bool remove_remote = false;
6986  if( std::find( loose_parts.begin(), loose_parts.end(), elem ) == loose_parts.end() ) {
6987  // part was removed elsewhere
6988  continue;
6989  }
6990  if( vpi_loose.has_flag( VPFLAG_POWER_TRANSFER ) ) {
6991  if( shed_cables == trinary::NONE ) {
6992  // Skip cables if we're only calling shed_loose_parts to remove parts with UNMOUNT_ON_MOVE.
6993  continue;
6994  }
6995  tripoint vp_loose_dst = here.getabs( dst ? *dst + vp_loose.precalc[1] : bub_part_pos( vp_loose ) );
6996  const int distance = rl_dist( vp_loose_dst, vp_loose.target.first );
6997  const int max_dist = vp_loose.get_base().max_link_length();
6998 
6999  if( distance > max_dist || shed_cables == trinary::ALL ) {
7001  _( "The %s's %s was detached!" ), name, vp_loose.name( false ) );
7002  remove_remote = true;
7003  } else {
7004  // cable still has some slack to it, so update the remote part's target and continue.
7005  const auto remote = get_remote_part( vp_loose );
7006  if( remote ) {
7007  remote->part().target.first = vp_loose_dst;
7008  remote->part().target.second = here.getabs( dst ? *dst : pos_bub() );
7009  }
7010  continue;
7011  }
7012  }
7013  const item drop = part_to_item( vp_loose );
7014  if( !magic ) {
7015  here.add_item_or_charges( global_part_pos3( vp_loose ), drop );
7016  }
7017 
7018  if( remove_remote ) {
7019  remove_remote_part( vp_loose );
7020  }
7021  remove_part( vp_loose );
7022  }
7023 }
int max_link_length() const
Definition: item.cpp:13564

References _, map::add_item_or_charges(), add_msg_if_player_sees(), ALL, bub_part_pos(), vehicle_part::get_base(), get_map(), get_remote_part(), map::getabs(), global_part_pos3(), vpart_info::has_flag(), vehicle_part::info(), loose_parts, m_warning, magic, item::max_link_length(), vehicle_part::name(), name, NONE, part(), part_to_item(), pos_bub(), vehicle_part::precalc, remove_part(), remove_remote_part(), rl_dist(), vehicle_part::target, and VPFLAG_POWER_TRANSFER.

Referenced by map::displace_vehicle(), and gain_moves().

◆ shift_if_needed()

bool vehicle::shift_if_needed ( map here)

Detect if the vehicle is currently missing a 0,0 part, and adjust if necessary.

Returns
bool true if the shift was needed.

Definition at line 7283 of file vehicle.cpp.

7284 {
7285  std::vector<int> vehicle_origin = parts_at_relative( point_zero, true );
7286  if( !vehicle_origin.empty() && !parts[ vehicle_origin[ 0 ] ].removed ) {
7287  // Shifting is not needed.
7288  return false;
7289  }
7290  //Find a frame, any frame, to shift to
7291  for( const vpart_reference &vp : get_all_parts() ) {
7292  if( vp.info().location == "structure"
7293  && !vp.has_feature( "PROTRUSION" )
7294  && !vp.part().removed ) {
7295  shift_parts( here, vp.mount() );
7296  refresh();
7297  return true;
7298  }
7299  }
7300  // There are only parts with PROTRUSION left, choose one of them.
7301  for( const vpart_reference &vp : get_all_parts() ) {
7302  if( !vp.part().removed ) {
7303  shift_parts( here, vp.mount() );
7304  refresh();
7305  return true;
7306  }
7307  }
7308  return false;
7309 }

References get_all_parts(), parts, parts_at_relative(), point_zero, refresh(), and shift_parts().

Referenced by merge_appliance_into_grid(), part_removal_cleanup(), remove_part(), and separate_from_grid().

◆ shift_parts()

void vehicle::shift_parts ( map here,
const point delta 
)

Shifts all parts of the vehicle by the given amounts, and then shifts the vehicle itself in the opposite direction.

The end result is that the vehicle appears to have not moved. Useful for re-zeroing a vehicle to ensure that a (0, 0) part is always present.

Parameters
deltaHow much to shift along each axis

Definition at line 7252 of file vehicle.cpp.

7253 {
7254  // Don't invalidate the active item cache's location!
7256  for( vehicle_part &elem : parts ) {
7257  elem.mount -= delta;
7258  }
7259 
7260  decltype( labels ) new_labels;
7261  for( const label &l : labels ) {
7262  new_labels.insert( label( l - delta, l.text ) );
7263  }
7264  labels = new_labels;
7265 
7266  decltype( loot_zones ) new_zones;
7267  for( auto const &z : loot_zones ) {
7268  new_zones.emplace( z.first - delta, z.second );
7269  }
7270  loot_zones = new_zones;
7271 
7272  pivot_anchor[0] -= delta;
7273  refresh();
7274  //Need to also update the map after this
7276 }
void subtract_locations(const point &delta)
Subtract delta from every item_reference's location.

References active_items, anonymous_namespace{item_tname.cpp}::label(), labels, loot_zones, parts, pivot_anchor, map::rebuild_vehicle_level_caches(), refresh(), and active_item_cache::subtract_locations().

Referenced by find_and_split_vehicles(), shift_if_needed(), and split_vehicles().

◆ should_enable_fake()

bool vehicle::should_enable_fake ( const tripoint fake_precalc,
const tripoint parent_precalc,
const tripoint neighbor_precalc 
) const
private

Definition at line 2289 of file vehicle_move.cpp.

2291 {
2292  // if parent's pos is diagonal to neighbor, but fake isn't, fake can fill a gap opened
2293  tripoint abs_parent_neighbor_diff = ( parent_precalc - neighbor_precalc ).abs();
2294  tripoint abs_fake_neighbor_diff = ( fake_precalc - neighbor_precalc ).abs();
2295  return ( abs_parent_neighbor_diff.x == 1 && abs_parent_neighbor_diff.y == 1 ) &&
2296  ( ( abs_fake_neighbor_diff.x == 1 && abs_fake_neighbor_diff.y == 0 ) ||
2297  ( abs_fake_neighbor_diff.x == 0 && abs_fake_neighbor_diff.y == 1 ) );
2298 }

References abs(), tripoint::x, and tripoint::y.

Referenced by update_active_fakes().

◆ slow_leak()

void vehicle::slow_leak ( )

Definition at line 5750 of file vehicle.cpp.

5751 {
5752  map &here = get_map();
5753  // for each badly damaged tanks (lower than 50% health), leak a small amount
5754  for( int part : fuel_containers ) {
5755  vehicle_part &p = parts[part];
5756  if( !p.is_leaking() || p.ammo_remaining() <= 0 ) {
5757  continue;
5758  }
5759 
5760  double health = p.health_percent();
5761  itype_id fuel = p.ammo_current();
5762  int qty = std::max( ( 0.5 - health ) * ( 0.5 - health ) * p.ammo_remaining() / 10, 1.0 );
5763  point q = coord_translate( p.mount );
5764  const tripoint dest = global_pos3() + tripoint( q, 0 );
5765 
5766  // damaged batteries self-discharge without leaking, plutonium leaks slurry
5767  if( fuel != fuel_type_battery && fuel != fuel_type_plutonium_cell ) {
5768  item leak( fuel, calendar::turn, qty );
5769  here.add_item_or_charges( dest, leak );
5770  p.ammo_consume( qty, global_part_pos3( p ) );
5771  } else if( fuel == fuel_type_plutonium_cell ) {
5772  if( p.ammo_remaining() >= PLUTONIUM_CHARGES / 10 ) {
5773  item leak( "plut_slurry_dense", calendar::turn, qty );
5774  here.add_item_or_charges( dest, leak );
5775  p.ammo_consume( qty * PLUTONIUM_CHARGES / 10, global_part_pos3( p ) );
5776  } else {
5778  }
5779  } else {
5780  p.ammo_consume( qty, global_part_pos3( p ) );
5781  }
5782  }
5783 }
constexpr int PLUTONIUM_CHARGES
bool is_leaking() const
is this part currently unable to retain to fluid/charge? this doesn't take into account whether or no...
static const itype_id fuel_type_plutonium_cell("plut_cell")

References map::add_item_or_charges(), vehicle_part::ammo_consume(), vehicle_part::ammo_current(), vehicle_part::ammo_remaining(), coord_translate(), fuel_containers, fuel_type_battery, fuel_type_plutonium_cell, get_map(), global_part_pos3(), global_pos3(), health, vehicle_part::health_percent(), vehicle_part::is_leaking(), max(), vehicle_part::mount, part(), parts, PLUTONIUM_CHARGES, tripoint, and calendar::turn.

Referenced by map::vehmove().

◆ slowdown()

int vehicle::slowdown ( int  velocity) const

Definition at line 107 of file vehicle_move.cpp.

108 {
109  double mps = vmiph_to_mps( std::abs( at_velocity ) );
110 
111  // slowdown due to air resistance is proportional to square of speed
112  double f_total_drag = coeff_air_drag() * mps * mps;
113  if( is_watercraft() ) {
114  // same with water resistance
115  f_total_drag += coeff_water_drag() * mps * mps;
116  } else if( !is_falling && !is_flying ) {
117  double f_rolling_drag = coeff_rolling_drag() * ( vehicles::rolling_constant_to_variable + mps );
118  // increase rolling resistance by up to 25x if the vehicle is skidding at right angle to facing
119  const double skid_factor = 1 + 24 * std::abs( units::sin( face.dir() - move.dir() ) );
120  f_total_drag += f_rolling_drag * skid_factor;
121  }
122  // check mass to make sure it's not 0 which happens for some reason
123  double accel_slowdown = total_mass().value() > 0 ? f_total_drag / to_kilogram( total_mass() ) : 0;
124  // converting m/s^2 to vmiph/s
125  int slowdown = mps_to_vmiph( accel_slowdown );
126  if( is_towing() ) {
127  vehicle *other_veh = tow_data.get_towed();
128  if( other_veh ) {
129  slowdown += other_veh->slowdown( at_velocity );
130  }
131  }
132  if( slowdown < 0 ) {
133  debugmsg( "vehicle %s has negative drag slowdown %d\n", name, slowdown );
134  }
136  "%s at %d vimph, f_drag %3.2f, drag accel %d vmiph - extra drag %d",
137  name, at_velocity, f_total_drag, slowdown, units::to_watt( static_drag() ) );
138  // plows slow rolling vehicles, but not falling or floating vehicles
139  if( !( is_falling || ( is_watercraft() && can_float() ) || is_flying ) ) {
141  }
142 
143  return std::max( 1, slowdown );
144 }
constexpr const value_type & value() const
Access the raw dimensionless value.
Definition: units.h:60
units::power static_drag(bool actual=true) const
Definition: vehicle.cpp:4584
double sin(angle a)
Definition: units.h:1102

References abs(), add_msg_debug, can_float(), coeff_air_drag(), coeff_rolling_drag(), coeff_water_drag(), debugmsg, debugmode::DF_VEHICLE_MOVE, tileray::dir(), face, towing_data::get_towed(), is_falling, is_flying, is_towing(), is_watercraft(), max(), move, mps_to_vmiph(), name, vehicles::rolling_constant_to_variable, units::sin(), slowdown(), static_drag(), units::to_kilogram(), units::to_watt(), total_mass(), tow_data, units::quantity< V, U >::value(), and vmiph_to_mps().

Referenced by gain_moves(), and slowdown().

◆ smart_controller_handle_turn()

void vehicle::smart_controller_handle_turn ( const std::optional< float > &  k_traction_cache = std::nullopt)

if smart controller is enabled, turns on and off engines depending on load and battery level

Parameters
thrustingmust be true when called from vehicle::thrust and vehicle is thrusting
k_traction_cachecached value of vehicle::k_traction, if empty, will be computed

Definition at line 146 of file vehicle_move.cpp.

147 {
148  // get settings or defaults
150 
152  smart_controller_state = std::nullopt;
153  return;
154  }
155 
157  return;
158  }
159 
160  // controlled engines
161  // note: contains indices of of elements in `engines` array, not the part ids
162  std::vector<int> c_engines;
163  bool has_electric_engine = false;
164  for( int i = 0; i < static_cast<int>( engines.size() ); ++i ) {
165  const vehicle_part &vp = parts[engines[i]];
166  const bool is_electric = is_engine_type( vp, fuel_type_battery );
167  if( ( is_electric || is_engine_type_combustion( vp ) ) &&
168  ( ( vp.is_available() && engine_fuel_left( vp ) ) || vp.enabled ) ) {
169  c_engines.push_back( i );
170  if( is_electric ) {
171  has_electric_engine = true;
172  }
173  }
174  }
175 
176  bool rotorcraft = is_flying && is_rotorcraft();
177 
178  Character &player_character = get_player_character();
179 
180  // bail and shut down
181  if( rotorcraft || c_engines.empty() || ( has_electric_engine && c_engines.size() == 1 ) ||
182  c_engines.size() > 5 ) {
183  for( const vpart_reference &vp : get_avail_parts( "SMART_ENGINE_CONTROLLER" ) ) {
184  vp.part().enabled = false;
185  }
186 
187  if( player_in_control( player_character ) ) {
188  if( rotorcraft ) {
189  add_msg( _( "Smart controller does not support flying vehicles." ) );
190  } else if( c_engines.empty() ) {
191  //TODO: make translation
192  add_msg( _( "Smart controller can not detect any controllable engine." ) );
193  } else if( c_engines.size() == 1 ) {
194  //TODO: make translation
195  add_msg( _( "Smart controller detects only a single electric engine." ) );
196  add_msg( _( "An electric engine does not need optimization." ) );
197  } else {
198  add_msg( _( "Smart controller does not support more than five engines." ) );
199  }
200  add_msg( m_bad, _( "Smart controller is shutting down." ) );
201  }
203  smart_controller_state = std::nullopt;
204  return;
205  }
206 
207  int cur_battery_level;
208  int max_battery_level;
209  std::tie( cur_battery_level, max_battery_level ) = battery_power_level();
210  int battery_level_percent = max_battery_level == 0 ? 0 : cur_battery_level * 100 /
211  max_battery_level;
212 
213  // ensure sane values
214  cfg.battery_hi = clamp( cfg.battery_hi, 0, 100 );
215  cfg.battery_lo = clamp( cfg.battery_lo, 0, cfg.battery_hi );
216 
217  // when battery > 90%, discharge is allowed
218  // otherwise trying to charge battery to 90% within 30 minutes
219  bool discharge_forbidden_soft = battery_level_percent <= cfg.battery_hi;
220  bool discharge_forbidden_hard = battery_level_percent <= cfg.battery_lo;
221  units::power target_charging_rate;
222  if( max_battery_level == 0 || !discharge_forbidden_soft ) {
223  target_charging_rate = 0_W;
224  } else {
225  target_charging_rate = units::from_watt( static_cast<std::int64_t>( ( max_battery_level *
226  cfg.battery_hi / 100 -
227  cur_battery_level ) * 10 / ( 6 * 3 ) ) );
228  }
229  // ( max_battery_level * battery_hi / 100 - cur_battery_level ) * (1000 / (60 * 30)) // originally
230  // ^ battery_hi% bat to W ^ ^ 30 minutes
231 
232  // using avg_velocity reduces unnecessary oscillations when traction is low
233  int accel_demand = std::max( std::abs( cruise_velocity - velocity ),
235  if( velocity != 0 && accel_demand == 0 ) {
236  accel_demand = 1; // to prevent zero fuel usage
237  }
238 
239  int velocity_demand = std::max( std::abs( this->velocity ), std::abs( cruise_velocity ) );
240 
241  // for stationary vehicles all velocity and acceleration calculations are skipped
242  bool is_stationary = avg_velocity == 0 && velocity_demand == 0 && accel_demand == 0;
243 
244  bool gas_engine_shutdown_forbidden = smart_controller_state &&
245  ( calendar::turn - smart_controller_state->gas_engine_last_turned_on ) <
246  15_seconds;
247 
248  smart_controller_cache cur_state;
249 
250  float traction = is_stationary ? 1.0f :
251  ( k_traction_cache ? *k_traction_cache : k_traction( get_map().vehicle_wheel_traction( *this ) ) );
252 
253  int prev_mask = 0;
254  // opt_ prefix denotes values for currently found "optimal" engine configuration
255  units::power opt_net_echarge_rate = net_battery_charge_rate( /* include_reactors = */ true );
256  // total engine fuel energy usage (J)
257  units::power opt_fuel_usage = 0_W;
258 
259  int opt_accel = is_stationary ? 1 : current_acceleration() * traction;
260  int opt_safe_vel = is_stationary ? 1 : safe_ground_velocity( true );
261  float cur_load_approx = static_cast<float>( std::min( accel_demand,
262  opt_accel ) ) / std::max( opt_accel, 1 );
263  float cur_load_alternator = std::min( 0.01f, static_cast<float>( alternator_load ) / 1000 );
264 
265  for( size_t i = 0; i < c_engines.size(); ++i ) {
266  const vehicle_part &vp = parts[engines[c_engines[i]]];
267  if( is_engine_on( vp ) ) {
268  const bool is_electric = is_engine_type( vp, fuel_type_battery );
269  prev_mask |= 1 << i;
270  units::power fu = engine_fuel_usage( vp ) * ( cur_load_approx + ( is_electric ? 0 :
271  cur_load_alternator ) );
272  opt_fuel_usage += fu;
273  if( is_electric ) {
274  opt_net_echarge_rate -= fu;
275  }
276  }
277  }
278  cur_state.created = calendar::turn;
279  cur_state.battery_percent = battery_level_percent;
280  cur_state.battery_net_charge_rate = opt_net_echarge_rate;
281  cur_state.velocity = avg_velocity;
282  cur_state.load = cur_load_approx + cur_load_alternator;
283  if( smart_controller_state ) {
284  cur_state.gas_engine_last_turned_on = smart_controller_state->gas_engine_last_turned_on;
285  }
286  cur_state.gas_engine_shutdown_forbidden = gas_engine_shutdown_forbidden;
287 
288  int opt_mask = prev_mask; // save current engine state, because it will be temporarily modified
289 
290  // if vehicle state has not change, skip actual optimization
292  std::abs( smart_controller_state->velocity - cur_state.velocity ) < 100 &&
293  std::abs( smart_controller_state->battery_percent - cur_state.battery_percent ) <= 2 &&
294  std::abs( smart_controller_state->load - cur_state.load ) < 0.1 && // load diff < 10%
295  smart_controller_state->battery_net_charge_rate == cur_state.battery_net_charge_rate &&
296  // reevaluate cache if when cache was created, gas engine shutdown was forbidden, but now it's not
297  !( smart_controller_state->gas_engine_shutdown_forbidden && !gas_engine_shutdown_forbidden )
298  ) {
300  return;
301  }
302 
303  // turn on/off combustion engines when necessary
304  if( !has_electric_engine ) {
305  Character &player_character = get_player_character();
306  if( !discharge_forbidden_soft && is_stationary && engine_on && !autopilot_on &&
307  !player_in_control( player_character ) ) {
308  stop_engines();
310  // temporary solution
311  } else if( discharge_forbidden_hard && !engine_on && cur_battery_level > 0 ) {
312  engine_on = true;
314  }
315  }
316 
317  // trying all combinations of engine state (max 31 iterations for 5 engines)
318  for( int mask = 1; mask < static_cast<int>( 1 << c_engines.size() ); ++mask ) {
319  if( mask == prev_mask ) {
320  continue;
321  }
322 
323  bool gas_engine_to_shut_down = false;
324  for( size_t i = 0; i < c_engines.size(); ++i ) {
325  vehicle_part &vp = parts[engines[c_engines[i]]];
326  bool old_state = ( prev_mask & ( 1 << i ) ) != 0;
327  bool new_state = ( mask & ( 1 << i ) ) != 0;
328  // switching enabled flag temporarily to perform calculations below
329  vp.enabled = new_state;
330 
331  if( old_state && !new_state && !is_engine_type( vp, fuel_type_battery ) ) {
332  gas_engine_to_shut_down = true;
333  }
334  }
335 
336  if( gas_engine_to_shut_down && gas_engine_shutdown_forbidden ) {
337  continue; // skip checking this state
338  }
339 
340  int safe_vel = is_stationary ? 1 : safe_ground_velocity( true );
341  int accel = is_stationary ? 1 : current_acceleration() * traction;
342  units::power fuel_usage = 0_W;
343  units::power net_echarge_rate = net_battery_charge_rate( /* include_reactors = */ true );
344  float load_approx = static_cast<float>( std::min( accel_demand, accel ) ) / std::max( accel, 1 );
346  float load_approx_alternator = std::min( 0.01f, static_cast<float>( alternator_load ) / 1000 );
347 
348  for( int e : c_engines ) {
349  const vehicle_part &vp = parts[engines[e]];
350  const bool is_electric = is_engine_type( vp, fuel_type_battery );
351  units::power fu = engine_fuel_usage( vp ) * ( load_approx + ( is_electric ? 0 :
352  load_approx_alternator ) );
353  fuel_usage += fu;
354  if( is_electric ) {
355  net_echarge_rate -= fu;
356  }
357  }
358 
359  if( std::forward_as_tuple(
360  !discharge_forbidden_hard || ( net_echarge_rate > 0_W ),
361  accel >= accel_demand,
362  opt_accel < accel_demand ? accel : 0, // opt_accel usage here is intentional
363  safe_vel >= velocity_demand,
364  opt_safe_vel < velocity_demand ? -safe_vel : 0, //opt_safe_vel usage here is intentional
365  !discharge_forbidden_soft || ( net_echarge_rate > target_charging_rate ),
366  -fuel_usage,
367  net_echarge_rate
368  ) >= std::forward_as_tuple(
369  !discharge_forbidden_hard || ( opt_net_echarge_rate > 0_W ),
370  opt_accel >= accel_demand,
371  opt_accel < accel_demand ? opt_accel : 0,
372  opt_safe_vel >= velocity_demand,
373  opt_safe_vel < velocity_demand ? -opt_safe_vel : 0,
374  !discharge_forbidden_soft || ( opt_net_echarge_rate > target_charging_rate ),
375  -opt_fuel_usage,
376  opt_net_echarge_rate
377  ) ) {
378  opt_mask = mask;
379  opt_fuel_usage = fuel_usage;
380  opt_net_echarge_rate = net_echarge_rate;
381  opt_accel = accel;
382  opt_safe_vel = safe_vel;
383 
384  cur_state.battery_net_charge_rate = net_echarge_rate;
385  cur_state.load = load_approx + load_approx_alternator;
386  // other `cur_state` fields do not change for different engine state combinations
387  }
388  }
389 
390  for( size_t i = 0; i < c_engines.size(); ++i ) { // return to prev state
391  vehicle_part &vp = parts[engines[c_engines[i]]];
392  vp.enabled = static_cast<bool>( prev_mask & ( 1 << i ) );
393  }
394 
395  if( opt_mask != prev_mask ) { // we found new configuration
396  bool failed_to_start = false;
397  bool turned_on_gas_engine = false;
398  for( size_t i = 0; i < c_engines.size(); ++i ) {
399  vehicle_part &vp = parts[engines[c_engines[i]]];
400  // ..0.. < ..1.. was off, new state on
401  if( ( prev_mask & ( 1 << i ) ) < ( opt_mask & ( 1 << i ) ) ) {
402  if( !start_engine( vp, true ) ) {
403  failed_to_start = true;
404  }
405  turned_on_gas_engine |= !is_engine_type( vp, fuel_type_battery );
406  }
407  }
408  if( failed_to_start ) {
409  this->smart_controller_state = std::nullopt;
410 
411  for( size_t i = 0; i < c_engines.size(); ++i ) { // return to prev state
412  vehicle_part &vp = parts[engines[c_engines[i]]];
413  vp.enabled = static_cast<bool>( prev_mask & ( 1 << i ) );
414  }
415  for( const vpart_reference &vp : get_avail_parts( "SMART_ENGINE_CONTROLLER" ) ) {
416  vp.part().enabled = false;
417  }
418  if( player_in_control( player_character ) ) {
419  add_msg( m_bad, _( "Smart controller failed to start an engine." ) );
420  add_msg( m_bad, _( "Smart controller is shutting down." ) );
421  }
423 
424  } else { //successfully changed engines state
425  for( size_t i = 0; i < c_engines.size(); ++i ) {
426  vehicle_part &vp = parts[engines[c_engines[i]]];
427  // was on, needs to be off
428  if( ( prev_mask & ( 1 << i ) ) > ( opt_mask & ( 1 << i ) ) ) {
429  start_engine( vp, false );
430  }
431  }
432  if( turned_on_gas_engine ) {
433  cur_state.gas_engine_last_turned_on = calendar::turn;
434  }
435  smart_controller_state = cur_state;
436 
437  if( player_in_control( player_character ) ) {
438  add_msg_debug( debugmode::DF_VEHICLE_MOVE, "Smart controller optimizes engine state." );
439  }
440  }
441  } else {
442  // as the optimization was performed (even without state change), cache needs to be updated as well
443  smart_controller_state = cur_state;
444  }
446 }
bool start_engine(vehicle_part &vp)
int current_acceleration(bool fueled=true) const
Definition: vehicle.cpp:3849
std::pair< int, int > battery_power_level() const
Definition: vehicle.cpp:5010
static const itype_id fuel_type_battery("battery")

References _, abs(), add_msg(), add_msg_debug, alternator_load, autopilot_on, avg_velocity, smart_controller_config::battery_hi, smart_controller_config::battery_lo, battery_power_level(), clamp(), cruise_velocity, current_acceleration(), debugmode::DF_VEHICLE_MOVE, sfx::do_vehicle_engine_sfx(), vehicle_part::enabled, engine_fuel_left(), engine_fuel_usage(), engine_on, engines, units::from_watt(), fuel_type_battery, fuel_usage(), get_avail_parts(), get_map(), get_player_character(), has_enabled_smart_controller, vehicle_part::is_available(), is_engine_on(), is_engine_type(), is_engine_type_combustion(), is_flying, is_rotorcraft(), k_traction(), m_bad, max(), min(), net_battery_charge_rate(), parts, player_in_control(), safe_ground_velocity(), smart_controller_cfg, smart_controller_state, start_engine(), stop_engines(), calendar::turn, update_alternator_load(), and velocity.

Referenced by idle(), and thrust().

◆ smash()

void vehicle::smash ( map m,
float  hp_percent_loss_min = 0.1f,
float  hp_percent_loss_max = 1.2f,
float  percent_of_parts_to_affect = 1.0f,
point  damage_origin = point_zero,
float  damage_size = 0 
)

Smashes up a vehicle that has already been placed; used for generating very damaged vehicles.

Additionally, any spot where two vehicles overlapped (i.e., any spot with multiple frames) will be completely destroyed, as that was the collision point.

Definition at line 863 of file vehicle.cpp.

865 {
866  for( vehicle_part &part : parts ) {
867  //Skip any parts already mashed up or removed.
868  if( part.is_broken() || part.removed ) {
869  continue;
870  }
871 
872  std::vector<int> parts_in_square = parts_at_relative( part.mount, true );
873  int structures_found = 0;
874  for( const int square_part_index : parts_in_square ) {
875  const vpart_info &vpi = parts[square_part_index].info();
876  if( vpi.location == part_location_structure ) {
877  structures_found++;
878  }
879  }
880 
881  if( structures_found > 1 ) {
882  //Destroy everything in the square
883  for( int idx : parts_in_square ) {
884  vehicle_part &vp = parts[idx];
885  vp.ammo_unset();
886  mod_hp( vp, -vp.hp() );
887  }
888  continue;
889  }
890 
891  int roll = dice( 1, 1000 );
892  int pct_af = ( percent_of_parts_to_affect * 1000.0f );
893  if( roll < pct_af ) {
894  double dist = damage_size == 0.0f ? 1.0f :
895  clamp( 1.0f - trig_dist( damage_origin, part.precalc[0].xy() ) /
896  damage_size, 0.0f, 1.0f );
897  //Everywhere else, drop by 10-120% of max HP (anything over 100 = broken)
898  const float roll = rng_float( hp_percent_loss_min * dist, hp_percent_loss_max * dist );
899  if( mod_hp( part, -part.info().durability * roll ) ) {
900  part.ammo_unset();
901  }
902  }
903  }
904 
905  std::unique_ptr<RemovePartHandler> handler_ptr;
906  // clear out any duplicated locations
907  for( int p = static_cast<int>( parts.size() ) - 1; p >= 0; p-- ) {
908  vehicle_part &part = parts[ p ];
909  if( part.removed ) {
910  continue;
911  }
912  std::vector<int> parts_here = parts_at_relative( part.mount, true );
913  for( int other_i = static_cast<int>( parts_here.size() ) - 1; other_i >= 0; other_i -- ) {
914  int other_p = parts_here[ other_i ];
915  if( p == other_p ) {
916  continue;
917  }
918  vehicle_part &vp1 = parts[p];
919  vehicle_part &vp2 = parts[other_p];
920  const vpart_info &vpi1 = vp1.info();
921  const vpart_info &vpi2 = vp2.info();
922 
923  if( vpi1.id == vpi2.id ||
924  ( !vpi1.location.empty() && vpi1.location == vpi2.location ) ) {
925  // Deferred creation of the handler to here so it is only created when actually needed.
926  if( !handler_ptr ) {
927  // This is a heuristic: we just assume the default handler is good enough when called
928  // on the main game map. And assume that we run from some mapgen code if called on
929  // another instance.
930  if( g && &get_map() == &m ) {
931  handler_ptr = std::make_unique<DefaultRemovePartHandler>();
932  } else {
933  handler_ptr = std::make_unique<MapgenRemovePartHandler>( m );
934  }
935  }
936  if( part.is_fake ) {
937  remove_part( vp1, *handler_ptr );
938  } else {
939  remove_part( vp2, *handler_ptr );
940  }
941  }
942  }
943  }
944 }
int trig_dist(const coords::coord_point< Point, Origin, Scale, LhsInBounds > &loc1, const coords::coord_point< Point, Origin, Scale, RhsInBounds > &loc2)
Definition: coordinates.h:762

References vehicle_part::ammo_unset(), clamp(), dice(), vpart_info::durability, g, get_map(), vehicle_part::hp(), vpart_info::id, vehicle_part::info(), vehicle_part::is_broken(), vehicle_part::is_fake, vpart_info::location, mod_hp(), vehicle_part::mount, part(), part_location_structure(), parts, parts_at_relative(), vehicle_part::precalc, remove_part(), vehicle_part::removed, rng_float(), and trig_dist().

Referenced by map::add_vehicle_to_map(), init_state(), MapExtras::mx_helicopter(), and monster::shove_vehicle().

◆ smash_security_system()

void vehicle::smash_security_system ( )
private
Mechanics reduces chance of damaging controls when smashing security system

Definition at line 438 of file vehicle_use.cpp.

439 {
440  int idx_security = -1;
441  int idx_controls = -1;
442  for( const int p : speciality ) { //get security and controls location
443  const vehicle_part &vp = part( p );
444  if( vp.info().has_flag( "SECURITY" ) && !vp.is_broken() ) {
445  idx_security = p;
446  idx_controls = part_with_feature( vp.mount, "CONTROLS", true );
447  break;
448  }
449  }
450  Character &player_character = get_player_character();
451  map &here = get_map();
452  if( idx_controls < 0 || idx_security < 0 ) {
453  debugmsg( "No security system found on vehicle." );
454  return; // both must be valid parts
455  }
456  vehicle_part &vp_controls = part( idx_controls );
457  vehicle_part &vp_security = part( idx_security );
458  ///\EFFECT_MECHANICS reduces chance of damaging controls when smashing security system
459  const float skill = player_character.get_skill_level( skill_mechanics );
460  const int percent_controls = 70 / ( 1 + skill );
461  const int percent_alarm = ( skill + 3 ) * 10;
462  const int rand = rng( 1, 100 );
463 
464  if( percent_controls > rand ) {
465  damage_direct( here, vp_controls, vp_controls.info().durability / 4 );
466 
467  if( vp_controls.removed || vp_controls.is_broken() ) {
468  player_character.controlling_vehicle = false;
469  is_alarm_on = false;
470  add_msg( _( "You destroy the controls…" ) );
471  } else {
472  add_msg( _( "You damage the controls." ) );
473  }
474  }
475  if( percent_alarm > rand ) {
476  damage_direct( here, vp_security, vp_security.info().durability / 5 );
477  // chance to disable alarm immediately, or disable on destruction
478  if( percent_alarm / 4 > rand || vp_security.is_broken() ) {
479  is_alarm_on = false;
480  }
481  }
482  add_msg( is_alarm_on ? _( "The alarm keeps going." ) : _( "The alarm stops." ) );
483 }

References _, add_msg(), Character::controlling_vehicle, damage_direct(), debugmsg, vpart_info::durability, get_map(), get_player_character(), Character::get_skill_level(), vpart_info::has_flag(), vehicle_part::info(), is_alarm_on, vehicle_part::is_broken(), vehicle_part::mount, part(), part_with_feature(), rand(), vehicle_part::removed, rng(), skill_mechanics, and speciality.

Referenced by build_interact_menu().

◆ spew_field()

void vehicle::spew_field ( double  joules,
int  part,
field_type_id  type,
int  intensity = 1 
) const

Definition at line 4003 of file vehicle.cpp.

4004 {
4005  if( rng( 1, 10000 ) > joules ) {
4006  return;
4007  }
4008  intensity = std::max( joules / 10000, static_cast<double>( intensity ) );
4009  const tripoint dest = exhaust_dest( part );
4011 }
int mod_field_intensity(const tripoint &p, const field_type_id &type, int offset)
Increment/decrement intensity of field entry at point, creating if not present, removing if intensity...
Definition: map.cpp:6429
int intensity
Definition: creature.h:240

References exhaust_dest(), get_map(), intensity, max(), map::mod_field_intensity(), part(), rng(), and type.

Referenced by noise_and_smoke().

◆ split_vehicles()

bool vehicle::split_vehicles ( map here,
const std::vector< std::vector< int >> &  new_vehs,
const std::vector< vehicle * > &  new_vehicles,
const std::vector< std::vector< point >> &  new_mounts,
std::vector< vehicle * > *  added_vehicles = nullptr 
)

Definition at line 2375 of file vehicle.cpp.

2380 {
2381  bool did_split = false;
2382  bool from_powergrid = is_powergrid();
2383  size_t i = 0;
2384  for( i = 0; i < new_vehs.size(); i ++ ) {
2385  std::vector<int> split_parts = new_vehs[ i ];
2386  if( split_parts.empty() ) {
2387  continue;
2388  }
2389  std::vector<point> split_mounts = new_mounts[ i ];
2390  did_split = true;
2391 
2392  vehicle *new_vehicle = nullptr;
2393  if( i < new_vehicles.size() ) {
2394  new_vehicle = new_vehicles[ i ];
2395  }
2396  int split_part0 = split_parts.front();
2397  tripoint new_v_pos3;
2398  point mnt_offset;
2399 
2400  // if one part is an appliance it means we're dealing with a power grid
2401  bool is_appliance = parts[split_part0].info().has_flag( flag_APPLIANCE );
2402  bool is_wiring = parts[split_part0].info().base_item == itype_wall_wiring;
2403 
2404  decltype( labels ) new_labels;
2405  decltype( loot_zones ) new_zones;
2406  if( new_vehicle == nullptr ) {
2407  // make sure the split_part0 is a legal 0,0 part
2408  if( split_parts.size() > 1 ) {
2409  for( int sp : split_parts ) {
2410  const vpart_info &vpi_split = parts[sp].info();
2411  if( vpi_split.location == part_location_structure && !vpi_split.has_flag( "PROTRUSION" ) ) {
2412  split_part0 = sp;
2413  break;
2414  }
2415  }
2416  }
2417  new_v_pos3 = global_part_pos3( parts[ split_part0 ] );
2418  mnt_offset = parts[ split_part0 ].mount;
2419  new_vehicle = here.add_vehicle( vehicle_prototype_none, new_v_pos3, face.dir() );
2420  if( new_vehicle == nullptr ) {
2421  // the split part was out of the map bounds.
2422  continue;
2423  }
2424  if( added_vehicles != nullptr ) {
2425  added_vehicles->emplace_back( new_vehicle );
2426  }
2427  // If we've split a power grid down to one part, rename it from "power grid" to its part name.
2428  new_vehicle->name = from_powergrid && split_parts.size() == 1 ?
2429  parts[ split_part0 ].info().name() : name;
2430  new_vehicle->owner = owner;
2431  new_vehicle->old_owner = old_owner;
2432  new_vehicle->move = move;
2433  new_vehicle->turn_dir = turn_dir;
2434  new_vehicle->velocity = velocity;
2435  new_vehicle->vertical_velocity = vertical_velocity;
2436  new_vehicle->cruise_velocity = cruise_velocity;
2437  new_vehicle->engine_on = engine_on;
2438  new_vehicle->tracking_on = tracking_on;
2439  new_vehicle->camera_on = camera_on;
2440 
2441  // If we were splitting appliances the resulting vehicles are still appliances
2442  if( is_appliance ) {
2443  new_vehicle->add_tag( flag_APPLIANCE );
2444  }
2445  if( is_wiring ) {
2446  new_vehicle->add_tag( flag_WIRING );
2447  }
2448  }
2449 
2450  std::vector<Character *> passengers;
2451  for( size_t new_part = 0; new_part < split_parts.size(); new_part++ ) {
2452  const int mov_part = split_parts[ new_part ];
2453  vehicle_part &vp_mov = part( mov_part );
2454  const vpart_info &vpi_mov = vp_mov.info();
2455  point cur_mount = vp_mov.mount;
2456  point new_mount = cur_mount;
2457  if( !split_mounts.empty() ) {
2458  new_mount = split_mounts[ new_part ];
2459  } else {
2460  new_mount -= mnt_offset;
2461  }
2462 
2463  Character *passenger = nullptr;
2464  // Unboard any entities standing on any transferred part
2465  if( vpi_mov.has_flag( VPFLAG_BOARDABLE ) ) {
2466  passenger = get_passenger( mov_part );
2467  if( passenger ) {
2468  passengers.push_back( passenger );
2469  }
2470  }
2471  // if this part is a towing part, transfer the tow_data to the new vehicle.
2472  if( vpi_mov.has_flag( "TOW_CABLE" ) ) {
2473  if( is_towed() ) {
2476  } else if( is_towing() ) {
2477  tow_data.get_towed()->tow_data.set_towing( new_vehicle, tow_data.get_towed() );
2479  }
2480  }
2481  // transfer the vehicle_part to the new vehicle
2482  new_vehicle->parts.emplace_back( vp_mov );
2483  new_vehicle->parts.back().mount = new_mount;
2484 
2485  // remove labels associated with the mov_part
2486  const auto iter = labels.find( label( cur_mount ) );
2487  if( iter != labels.end() ) {
2488  std::string label_str = iter->text;
2489  labels.erase( iter );
2490  new_labels.insert( label( new_mount, label_str ) );
2491  }
2492  // Prepare the zones to be moved to the new vehicle
2493  const std::pair<std::unordered_multimap<point, zone_data>::iterator, std::unordered_multimap<point, zone_data>::iterator>
2494  zones_on_point = loot_zones.equal_range( cur_mount );
2495  for( std::unordered_multimap<point, zone_data>::const_iterator lz_iter = zones_on_point.first;
2496  lz_iter != zones_on_point.second; ++lz_iter ) {
2497  new_zones.emplace( new_mount, lz_iter->second );
2498  }
2499 
2500  // Erasing on the key removes all the zones from the point at once
2501  loot_zones.erase( cur_mount );
2502 
2503  // The zone manager will be updated when we next interact with it through get_vehicle_zones
2504  zones_dirty = true;
2505 
2506  // remove the passenger from the old vehicle
2507  if( passenger ) {
2509  vp_mov.passenger_id = character_id();
2510  }
2511  // indicate the part needs to be removed from the old vehicle
2512  vp_mov.removed = true;
2513  }
2514 
2515  // We want to create the vehicle zones after we've setup the parts
2516  // because we need only to move the zone once per mount, not per part. If we move per
2517  // part, we will end up with duplicates of the zone per part on the same mount
2518  for( std::pair<point, zone_data> zone : new_zones ) {
2519  zone_manager::get_manager().create_vehicle_loot_zone( *new_vehicle, zone.first, zone.second );
2520  }
2521 
2522  // create_vehicle_loot_zone marks the vehicle as not dirty but since we got these zones
2523  // in an unknown state from the previous vehicle, we need to let the cache rebuild next
2524  // time we interact with them
2525  new_vehicle->zones_dirty = true;
2526 
2527  here.dirty_vehicle_list.insert( new_vehicle );
2530  if( !new_labels.empty() ) {
2531  new_vehicle->labels = new_labels;
2532  }
2533 
2534  if( split_mounts.empty() ) {
2535  new_vehicle->refresh();
2536  } else {
2537  // include refresh
2538  new_vehicle->shift_parts( here, point_zero - mnt_offset );
2539  }
2540 
2541  // update the precalc points
2542  new_vehicle->precalc_mounts( 0, new_vehicle->turn_dir, point() );
2543  new_vehicle->precalc_mounts( 1, new_vehicle->skidding ?
2544  new_vehicle->turn_dir : new_vehicle->face.dir(),
2545  new_vehicle->pivot_point() );
2546  if( !passengers.empty() ) {
2547  new_vehicle->relocate_passengers( passengers );
2548  }
2549  }
2550  return did_split;
2551 }
bool set_towing(vehicle *tower_veh, vehicle *towed_veh)
Definition: vehicle.cpp:6816
void relocate_passengers(const std::vector< Character * > &passengers) const
Definition: vehicle.cpp:2363
static const itype_id itype_wall_wiring("wall_wiring")

References add_tag(), map::add_vehicle(), camera_on, character_id, towing_data::clear_towing(), zone_manager::create_vehicle_loot_zone(), cruise_velocity, tileray::dir(), map::dirty_vehicle_list, engine_on, face, flag_APPLIANCE(), flag_WIRING(), zone_manager::get_manager(), get_passenger(), towing_data::get_towed(), towing_data::get_towed_by(), global_part_pos3(), vpart_info::has_flag(), vehicle_part::info(), is_appliance(), is_powergrid(), is_towed(), is_towing(), itype_wall_wiring, anonymous_namespace{item_tname.cpp}::label(), labels, vpart_info::location, loot_zones, vehicle_part::mount, move, name, old_owner, owner, part(), part_location_structure(), parts, passenger_flag, vehicle_part::passenger_id, pivot_point(), point_zero, precalc_mounts(), refresh(), relocate_passengers(), vehicle_part::remove_flag(), vehicle_part::removed, map::set_seen_cache_dirty(), towing_data::set_towing(), map::set_transparency_cache_dirty(), shift_parts(), skidding, sm_pos, tow_data, tracking_on, tripoint_zero, turn_dir, vehicle_prototype_none, velocity, vertical_velocity, VPFLAG_BOARDABLE, tripoint::z, and zones_dirty.

Referenced by find_and_split_vehicles(), remove_carried_vehicle(), and separate_from_grid().

◆ start_engine() [1/2]

bool vehicle::start_engine ( vehicle_part vp)

Definition at line 629 of file vehicle_use.cpp.

630 {
631  const vpart_info &vpi = vp.info();
632  if( !is_engine_on( vp ) ) {
633  return false;
634  }
635 
636  Character &player_character = get_player_character();
637  const bool out_of_fuel = !auto_select_fuel( vp );
638  if( out_of_fuel ) {
639  if( vpi.fuel_type == fuel_type_muscle ) {
640  // Muscle engines cannot start with broken limbs
641  if( vpi.has_flag( "MUSCLE_ARMS" ) && !player_character.has_two_arms_lifting() ) {
642  add_msg( _( "You cannot use %s with a broken arm." ), vp.name() );
643  return false;
644  } else if( vpi.has_flag( "MUSCLE_LEGS" ) && ( player_character.get_working_leg_count() < 2 ) ) {
645  add_msg( _( "You cannot use %s without at least two legs." ), vp.name() );
646  return false;
647  }
648  } else {
649  add_msg( _( "Looks like the %1$s is out of %2$s." ), vp.name(),
650  item::nname( vpi.fuel_type ) );
651  return false;
652  }
653  }
654 
655  if( has_part( player_character.pos(), "NEED_LEG" ) &&
656  player_character.get_working_leg_count() < 1 &&
657  !has_part( player_character.pos(), "IGNORE_LEG_REQUIREMENT" ) ) {
658  add_msg( _( "You need at least one leg to control the %s." ), vp.name() );
659  return false;
660  }
661  if( has_part( player_character.pos(), "INOPERABLE_SMALL" ) &&
662  ( player_character.get_size() == creature_size::small ||
663  player_character.get_size() == creature_size::tiny ) &&
664  !has_part( player_character.pos(), "IGNORE_HEIGHT_REQUIREMENT" ) ) {
665  add_msg( _( "You are too short to reach the pedals!" ) );
666  return false;
667  }
668 
669  const double dmg = vp.damage_percent();
670  const time_duration start_time = engine_start_time( vp );
671  const tripoint pos = global_part_pos3( vp );
672 
673  if( ( 1 - dmg ) < vpi.engine_info->backfire_threshold &&
674  one_in( vpi.engine_info->backfire_freq ) ) {
675  backfire( vp );
676  } else {
677  sounds::sound( pos, to_seconds<int>( start_time ) * 10, sounds::sound_t::movement,
678  string_format( _( "the %s bang as it starts!" ), vp.name() ), true, "vehicle",
679  "engine_bangs_start" );
680  }
681 
682  // Immobilizers need removing before the vehicle can be started
683  if( vp.has_fault_flag( "IMMOBILIZER" ) ) {
685  string_format( _( "the %s making a long beep." ), vp.name() ), true, "vehicle",
686  "fault_immobiliser_beep" );
687  return false;
688  }
689 
690  // Engine with starter motors can fail on both battery and starter motor
691  if( vp.faults_potential().count( fault_engine_starter ) ) {
692  if( vp.has_fault_flag( "BAD_STARTER" ) ) {
694  string_format( _( "the %s clicking once." ), vp.name() ), true, "vehicle",
695  "engine_single_click_fail" );
696  return false;
697  }
698 
699  const double cold_factor = engine_cold_factor( vp );
700  const units::power start_power = -part_epower( vp ) * ( dmg * 5 + cold_factor * 2 + 10 );
701  const int start_bat = power_to_energy_bat( start_power, start_time );
702  if( discharge_battery( start_bat ) != 0 ) {
704  string_format( _( "the %s rapidly clicking." ), vp.name() ), true, "vehicle",
705  "engine_multi_click_fail" );
706  return false;
707  }
708  }
709 
710  // Engines always fail to start with faulty fuel pumps
711  if( vp.has_fault_flag( "BAD_FUEL_PUMP" ) ) {
713  string_format( _( "the %s quickly stuttering out." ), vp.name() ), true, "vehicle",
714  "engine_stutter_fail" );
715  return false;
716  }
717 
718  // Damaged non-electric engines have a chance of failing to start
720  x_in_y( dmg * 100, 120 ) ) {
722  string_format( _( "the %s clanking and grinding." ), vp.name() ), true, "vehicle",
723  "engine_clanking_fail" );
724  return false;
725  }
727  string_format( _( "the %s starting." ), vp.name() ) );
728 
729  std::string variant = vpi.id.str();
730 
731  if( sfx::has_variant_sound( "engine_start", variant ) ) {
732  // has special sound variant for this vpart id
733  } else if( vpi.fuel_type == fuel_type_muscle ) {
734  variant = "muscle";
735  } else if( is_engine_type( vp, fuel_type_wind ) ) {
736  variant = "wind";
737  } else if( is_engine_type( vp, fuel_type_battery ) ) {
738  variant = "electric";
739  } else {
740  variant = "combustion";
741  }
742  sfx::play_variant_sound( "engine_start", variant, vpi.engine_info->noise_factor );
743  return true;
744 }
creature_size get_size() const override
Get size class of character.
Definition: character.cpp:824
time_duration engine_start_time(const vehicle_part &vp) const
bool has_variant_sound(const std::string &id, const std::string &variant)
Definition: sounds.cpp:2027
static const fault_id fault_engine_starter("fault_engine_starter")
static const itype_id fuel_type_wind("wind")

References _, add_msg(), sounds::alarm, auto_select_fuel(), backfire(), vehicle_part::damage_percent(), discharge_battery(), engine_cold_factor(), vpart_info::engine_info, engine_start_time(), fault_engine_starter, vehicle_part::faults_potential(), vpart_info::fuel_type, fuel_type_battery, fuel_type_muscle, fuel_type_wind, get_player_character(), Character::get_size(), Character::get_working_leg_count(), global_part_pos3(), vehicle_part::has_fault_flag(), vpart_info::has_flag(), has_part(), Character::has_two_arms_lifting(), sfx::has_variant_sound(), vpart_info::id, vehicle_part::info(), is_engine_on(), is_engine_type(), sounds::movement, vehicle_part::name(), item::nname(), one_in(), part_epower(), sfx::play_variant_sound(), Creature::pos(), pos, power_to_energy_bat(), small, sounds::sound(), string_id< T >::str(), string_format(), tiny, and x_in_y().

Referenced by smart_controller_handle_turn(), start_engine(), and activity_handlers::start_engines_finish().

◆ start_engine() [2/2]

bool vehicle::start_engine ( vehicle_part vp,
bool  turn_on 
)

Definition at line 5042 of file vehicle.cpp.

5043 {
5044  if( vp.enabled == turn_on ) {
5045  return false;
5046  }
5047  bool res = false;
5048  if( turn_on ) {
5049  vp.enabled = true;
5050  // prevent starting of the faulty engines
5051  if( !start_engine( vp ) ) {
5052  vp.enabled = false;
5053  } else {
5054  res = true;
5055  }
5056  } else {
5057  vp.enabled = false;
5058  res = true;
5059  }
5060  return res;
5061 }

References vehicle_part::enabled, and start_engine().

◆ start_engines()

void vehicle::start_engines ( bool  take_control = false,
bool  autodrive = false 
)

Definition at line 778 of file vehicle_use.cpp.

779 {
780  bool has_engine = std::any_of( engines.begin(), engines.end(), [&]( int idx ) {
781  return parts[ idx ].enabled && !parts[ idx ].is_broken();
782  } );
783 
784  // if no engines enabled then enable all before trying to start the vehicle
785  if( !has_engine ) {
786  for( const int p : engines ) {
787  vehicle_part &vp = parts[p];
788  vp.enabled = !vp.is_broken();
789  }
790  }
791 
792  time_duration start_time = 0_seconds;
793  // record the first usable engine as the referenced position checked at the end of the engine starting activity
794  bool has_starting_engine_position = false;
795  tripoint_bub_ms starting_engine_position;
796  for( const int p : engines ) {
797  const vehicle_part &vp = parts[p];
798  if( !has_starting_engine_position && !vp.is_broken() && vp.enabled ) {
799  starting_engine_position = bub_part_pos( vp );
800  has_starting_engine_position = true;
801  }
802  has_engine = has_engine || is_engine_on( vp );
803  start_time = std::max( start_time, engine_start_time( vp ) );
804  }
805 
806  if( !has_starting_engine_position ) {
807  starting_engine_position = {};
808  }
809 
810  if( !has_engine ) {
811  add_msg( m_info, _( "The %s doesn't have an engine!" ), name );
812  refresh();
813  return;
814  }
815 
816  Character &player_character = get_player_character();
817  if( take_control && !player_character.controlling_vehicle ) {
818  player_character.controlling_vehicle = true;
819  add_msg( _( "You take control of the %s." ), name );
820  }
821  if( !autodrive ) {
822  player_character.assign_activity( ACT_START_ENGINES, to_moves<int>( start_time ) );
823  player_character.activity.relative_placement =
824  starting_engine_position - player_character.pos_bub();
825  player_character.activity.values.push_back( take_control );
826  }
827  refresh();
828 }
player_activity activity
Definition: character.h:2709
tripoint_bub_ms pos_bub() const
Definition: creature.cpp:183
std::vector< int > values
tripoint_rel_ms relative_placement
static const activity_id ACT_START_ENGINES("ACT_START_ENGINES")

References _, ACT_START_ENGINES, Character::activity, add_msg(), Character::assign_activity(), bub_part_pos(), Character::controlling_vehicle, vehicle_part::enabled, engine_start_time(), engines, get_player_character(), vehicle_part::is_broken(), is_engine_on(), m_info, max(), name, parts, Creature::pos_bub(), refresh(), player_activity::relative_placement, and player_activity::values.

Referenced by build_interact_menu(), control_engines(), game::control_vehicle(), enable_patrol(), iuse::remoteveh(), and toggle_autopilot().

◆ static_drag()

units::power vehicle::static_drag ( bool  actual = true) const

Definition at line 4584 of file vehicle.cpp.

4585 {
4586  bool is_actively_towed = is_towed();
4587  if( is_actively_towed ) {
4588  vehicle *towing_veh = tow_data.get_towed_by();
4589  if( !towing_veh ) {
4590  is_actively_towed = false;
4591  } else {
4592  const int tow_index = get_tow_part();
4593  if( tow_index == -1 ) {
4594  is_actively_towed = false;
4595  } else {
4596  const int other_tow_index = towing_veh->get_tow_part();
4597  if( other_tow_index == -1 ) {
4598  is_actively_towed = false;
4599  } else {
4600  map &here = get_map();
4601  const tripoint towed_tow_point = here.getabs( global_part_pos3( tow_index ) );
4602  const tripoint tower_tow_point = here.getabs( towing_veh->global_part_pos3( other_tow_index ) );
4603  is_actively_towed = rl_dist( towed_tow_point, tower_tow_point ) >= 6;
4604  }
4605  }
4606  }
4607  }
4608 
4609  return extra_drag + ( actual && !engine_on && !is_actively_towed ? -1500_W : 0_W );
4610 }

References engine_on, extra_drag, get_map(), get_tow_part(), towing_data::get_towed_by(), map::getabs(), global_part_pos3(), is_towed(), rl_dist(), and tow_data.

Referenced by veh_interact::display_stats(), and slowdown().

◆ steering_effectiveness()

float vehicle::steering_effectiveness ( ) const

Definition at line 4769 of file vehicle.cpp.

4770 {
4771  if( in_deep_water ) {
4772  // I'M ON A BOAT
4773  return can_float() ? 1.0f : 0.0f;
4774  }
4775  if( is_flying ) {
4776  // I'M IN THE AIR
4777  return is_rotorcraft() ? 1.0f : 0.0f;
4778  }
4779  // irksome special case for boats in shallow water
4780  if( is_watercraft() && can_float() ) {
4781  return 1.0f;
4782  }
4783 
4784  if( steering.empty() ) {
4785  return -1.0f; // No steering installed
4786  }
4787  // no steering if only steering part is animal harness without animal in it
4788  const vehicle_part &vp = parts[steering[0]];
4789  if( steering.size() == 1 && vp.info().fuel_type == fuel_type_animal && !get_harnessed_animal() ) {
4790  return -2.0f;
4791  }
4792  // For now, you just need one wheel working for 100% effective steering.
4793  // TODO: return something less than 1.0 if the steering isn't so good
4794  // (unbalanced, long wheelbase, back-heavy vehicle with front wheel steering,
4795  // etc)
4796  for( const int p : steering ) {
4797  const vehicle_part &vp = parts[p];
4798  if( vp.is_available() ) {
4799  return 1.0f;
4800  }
4801  }
4802 
4803  // We have steering, but it's all broken.
4804  return 0.0f;
4805 }

References can_float(), vpart_info::fuel_type, fuel_type_animal, get_harnessed_animal(), in_deep_water, vehicle_part::info(), vehicle_part::is_available(), is_flying, is_rotorcraft(), is_watercraft(), parts, and steering.

Referenced by handling_difficulty(), pldrive(), selfdrive(), and wheel_state_description().

◆ stop()

void vehicle::stop ( )

Definition at line 682 of file vehicle_move.cpp.

683 {
684  velocity = 0;
685  skidding = false;
686  move = face;
687  last_turn = 0_degrees;
688  of_turn_carry = 0;
689  map &here = get_map();
690  for( const tripoint &p : get_points() ) {
691  if( here.inbounds( p ) ) {
692  here.memory_cache_dec_set_dirty( p, true );
693  }
694  }
695 }

References face, get_map(), get_points(), map::inbounds(), last_turn, map::memory_cache_dec_set_dirty(), move, of_turn_carry, skidding, and velocity.

Referenced by act_on_map(), consume_fuel(), map::displace_vehicle(), drive_to_local_target(), gain_moves(), handbrake(), map::move_vehicle(), precollision_check(), and thrust().

◆ stop_autodriving()

void vehicle::stop_autodriving ( bool  apply_brakes = true)

◆ stop_engines()

void vehicle::stop_engines ( )

Definition at line 746 of file vehicle_use.cpp.

747 {
748  vehicle_noise = 0;
749  engine_on = false;
750  for( const int p : engines ) {
751  const vehicle_part &vp = parts[p];
752  if( !is_engine_on( vp ) ) {
753  continue;
754  }
755 
756  sounds::sound( global_part_pos3( vp ), 2, sounds::sound_t::movement, _( "the engine go silent" ) );
757 
758  std::string variant = vp.info().id.str();
759 
760  if( sfx::has_variant_sound( "engine_stop", variant ) ) {
761  // has special sound variant for this vpart id
762  } else if( is_engine_type( vp, fuel_type_battery ) ) {
763  variant = "electric";
764  } else if( is_engine_type( vp, fuel_type_muscle ) ) {
765  variant = "muscle";
766  } else if( is_engine_type( vp, fuel_type_wind ) ) {
767  variant = "wind";
768  } else {
769  variant = "combustion";
770  }
771 
772  sfx::play_variant_sound( "engine_stop", variant, vp.info().engine_info->noise_factor );
773  }
775  refresh();
776 }

References _, sfx::do_vehicle_engine_sfx(), vpart_info::engine_info, engine_on, engines, fuel_type_battery, fuel_type_muscle, fuel_type_wind, global_part_pos3(), sfx::has_variant_sound(), vpart_info::id, vehicle_part::info(), is_engine_on(), is_engine_type(), sounds::movement, parts, sfx::play_variant_sound(), refresh(), sounds::sound(), string_id< T >::str(), and vehicle_noise.

Referenced by build_interact_menu(), smart_controller_handle_turn(), and toggle_autopilot().

◆ strain()

float vehicle::strain ( ) const

Definition at line 4612 of file vehicle.cpp.

4613 {
4614  if( velocity == 0.0 ) {
4615  return 0.0f;
4616  }
4617  int mv = max_velocity();
4618  int sv = safe_velocity();
4619  if( mv <= sv ) {
4620  mv = sv + 1;
4621  }
4622  if( velocity < sv && velocity > -sv ) {
4623  return 0;
4624  } else {
4625  return static_cast<float>( std::abs( velocity ) - sv ) / static_cast<float>( mv - sv );
4626  }
4627 }

References abs(), max_velocity(), safe_velocity(), and velocity.

Referenced by consume_fuel(), do_engine_damage(), print_speed_gauge(), thrust(), and display::vehicle_cruise_text_color().

◆ sufficient_wheel_config()

bool vehicle::sufficient_wheel_config ( ) const

Definition at line 4629 of file vehicle.cpp.

4630 {
4631  if( wheelcache.empty() ) {
4632  // No wheels!
4633  return false;
4634  } else if( wheelcache.size() == 1 ) {
4635  //Has to be a stable wheel, and one wheel can only support a 1-3 tile vehicle
4636  if( !part( wheelcache[0] ).info().has_flag( "STABLE" ) ||
4638  return false;
4639  }
4640  }
4641  return true;
4642 }

References all_parts_at_location(), part(), part_location_structure(), om_direction::size, and wheelcache.

Referenced by valid_wheel_config(), wait(), and wheel_state_description().

◆ suspend_refresh()

void vehicle::suspend_refresh ( )

Disable or enable refresh() ; used to speed up performance when creating a vehicle.

Definition at line 6135 of file vehicle.cpp.

6136 {
6137  // disable refresh and cache recalculation
6138  no_refresh = true;
6139  mass_dirty = false;
6140  mass_center_precalc_dirty = false;
6142  coeff_rolling_dirty = false;
6143  coeff_air_dirty = false;
6144  coeff_water_dirty = false;
6145  coeff_air_changed = false;
6146 }

References coeff_air_changed, coeff_air_dirty, coeff_rolling_dirty, coeff_water_dirty, mass_center_no_precalc_dirty, mass_center_precalc_dirty, mass_dirty, and no_refresh.

Referenced by vehicles::finalize_prototypes().

◆ thrust()

void vehicle::thrust ( int  thd,
int  z = 0 
)

Definition at line 448 of file vehicle_move.cpp.

449 {
450  //if vehicle is stopped, set target direction to forward.
451  //ensure it is not skidding. Set turns used to 0.
452  if( !is_moving() && z == 0 ) {
453  turn_dir = face.dir();
454  stop();
455  }
456  bool pl_ctrl = player_in_control( get_player_character() );
457 
458  // No need to change velocity if there are no wheels
459  if( ( is_watercraft() && can_float() ) || ( is_rotorcraft() && ( z != 0 || is_flying ) ) ) {
460  // we're good
461  } else if( in_deep_water && !can_float() ) {
462  stop();
463  if( pl_ctrl ) {
464  add_msg( _( "The %s is too leaky!" ), name );
465  }
466  return;
467  } else if( !valid_wheel_config() && z == 0 ) {
468  stop();
469  if( pl_ctrl ) {
470  add_msg( _( "The %s doesn't have enough wheels to move!" ), name );
471  }
472  return;
473  }
474  // Accelerate (true) or brake (false)
475  bool thrusting = true;
476  if( velocity ) {
477  int sgn = ( velocity < 0 ) ? -1 : 1;
478  thrusting = ( sgn == thd );
479  }
480 
481  // TODO: Pass this as an argument to avoid recalculating
482  float traction = k_traction( get_map().vehicle_wheel_traction( *this ) );
483 
484  if( thrusting ) {
485  smart_controller_handle_turn( traction );
486  }
487 
488  int accel = current_acceleration() * traction;
489  if( accel < 200 && velocity > 0 && is_towing() ) {
490  if( pl_ctrl ) {
491  add_msg( _( "The %s struggles to pull the %s on this surface!" ), name,
492  tow_data.get_towed()->name );
493  }
494  return;
495  }
496  if( thrusting && accel == 0 ) {
497  if( pl_ctrl ) {
498  if( has_engine_type( fuel_type_muscle, true ) ) {
499  add_msg( _( "The %s is too heavy to move!" ), name );
500  } else {
501  add_msg( n_gettext( "The %s is too heavy for its engine!",
502  "The %s is too heavy for its engines!",
503  engines.size() ), name );
504  }
505  }
506  return;
507  }
508  const int max_vel = traction * max_velocity();
509  // maximum braking is 20 mph/s, assumes high friction tires
510  const int max_brake = 20 * 100;
511  //pos or neg if accelerator or brake
512  int vel_inc = ( accel + ( thrusting ? 0 : max_brake ) ) * thd;
513  // Reverse is only 60% acceleration, unless an electric motor is in use
514  if( thd == -1 && thrusting && !has_engine_type( fuel_type_battery, true ) ) {
515  vel_inc = .6 * vel_inc;
516  }
517 
518  //find ratio of used acceleration to maximum available, returned in tenths of a percent
519  //so 1000 = 100% and 453 = 45.3%
520  int load;
521  if( accel != 0 ) {
522  int effective_cruise = std::min( cruise_velocity, max_vel );
523  if( thd > 0 ) {
524  vel_inc = std::min( vel_inc, effective_cruise - velocity );
525  } else {
526  vel_inc = std::max( vel_inc, effective_cruise - velocity );
527  }
528  if( thrusting ) {
529  load = 1000 * std::abs( vel_inc ) / accel;
530  } else {
531  // brakes provide 20 mph/s of slowdown and the rest is engine braking
532  // TODO: braking depends on wheels, traction, driver skill
533  load = 1000 * std::max( 0, std::abs( vel_inc ) - max_brake ) / accel;
534  }
535  } else {
536  load = ( thrusting ? 1000 : 0 );
537  }
538  // rotorcraft need to spend 15% of load to hover, 30% to change z
539  if( is_rotorcraft() && ( z > 0 || is_flying_in_air() ) ) {
540  load = std::max( load, z > 0 ? 300 : 150 );
541  thrusting = true;
542  }
543 
544  // only consume resources if engine accelerating
545  if( load >= 1 && thrusting ) {
546  //abort if engines not operational
547  if( total_power() <= 0_W || !engine_on || ( z == 0 && accel == 0 ) ) {
548  if( pl_ctrl ) {
549  if( total_power( false ) <= 0_W ) {
550  add_msg( m_info, _( "The %s doesn't have an engine!" ), name );
551  } else if( has_engine_type( fuel_type_muscle, true ) ) {
552  add_msg( m_info, _( "The %s's mechanism is out of reach!" ), name );
553  } else if( !engine_on ) {
554  add_msg( _( "The %s's engine isn't on!" ), name );
555  } else if( traction < 0.01f ) {
556  add_msg( _( "The %s is stuck." ), name );
557  } else {
558  add_msg( _( "The %s's engine emits a sneezing sound." ), name );
559  }
560  }
561  cruise_velocity = 0;
562  return;
563  }
564  // helicopters improve efficiency the closer they get to 50-70 knots
565  // then it drops off as they go over that.
566  // see https://i.stack.imgur.com/0zIO7.jpg
567  if( is_rotorcraft() && is_flying_in_air() ) {
568  const int velocity_kt = velocity * 0.01;
569  int value;
570  if( velocity_kt < 70 ) {
571  value = 49 * std::pow( velocity_kt, 3 ) -
572  4118 * std::pow( velocity_kt, 2 ) - 76512 * velocity_kt + 18458000;
573  } else {
574  value = 1864 * std::pow( velocity_kt, 2 ) - 272190 * velocity_kt + 19473000;
575  }
576  value *= 0.0001;
577  load = std::max( 200, std::min( 1000, ( ( value / 2 ) + 100 ) ) );
578  }
579  //make noise and consume fuel
581  consume_fuel( load + alternator_load, false );
582  if( z != 0 && is_rotorcraft() ) {
583  requested_z_change = z;
584  }
585  //break the engines a bit, if going too fast.
586  const int strn = static_cast<int>( strain() * strain() * 100 );
587  for( const int p : engines ) {
588  do_engine_damage( parts[p], strn );
589  }
590  }
591 
592  //wheels aren't facing the right way to change velocity properly
593  //lower down, since engines should be getting damaged anyway
594  if( skidding ) {
595  return;
596  }
597 
598  //change vehicles velocity
599  if( ( velocity > 0 && velocity + vel_inc < 0 ) || ( velocity < 0 && velocity + vel_inc > 0 ) ) {
600  //velocity within braking distance of 0
601  stop();
602  } else {
603  // Increase velocity up to max_vel or min_vel, but not above.
604  const int min_vel = max_reverse_velocity();
605  if( vel_inc > 0 ) {
606  // Don't allow braking by accelerating (could happen with damaged engines)
607  velocity = std::max( velocity, std::min( velocity + vel_inc, max_vel ) );
608  } else {
609  velocity = std::min( velocity, std::max( velocity + vel_inc, min_vel ) );
610  }
611  }
612  // If you are going faster than the animal can handle, harness is damaged
613  // Animal may come free ( and possibly hit by vehicle )
614  for( size_t e = 0; e < parts.size(); e++ ) {
615  vehicle_part &vp = parts[e];
616  if( vp.info().fuel_type == fuel_type_animal && engines.size() != 1 ) {
617  monster *mon = get_monster( e );
618  if( mon != nullptr && mon->has_effect( effect_harnessed ) ) {
619  if( velocity > mon->get_speed() * 12 ) {
620  add_msg( m_bad, _( "Your %s is not fast enough to keep up with the %s" ), mon->get_name(), name );
621  int dmg = rng( 0, 10 );
622  damage_direct( get_map(), vp, dmg );
623  }
624  }
625  }
626  }
627 }
virtual int get_speed() const
Definition: creature.cpp:2138
std::string get_name() const override
Definition: monster.cpp:717
void do_engine_damage(vehicle_part &vp, int strain)
Definition: vehicle.cpp:5608
static const itype_id fuel_type_muscle("muscle")

References _, abs(), add_msg(), alternator_load, can_float(), consume_fuel(), cruise_velocity, current_acceleration(), damage_direct(), tileray::dir(), do_engine_damage(), effect_harnessed, engine_on, engines, face, vpart_info::fuel_type, fuel_type_animal, fuel_type_battery, fuel_type_muscle, get_map(), get_monster(), monster::get_name(), get_player_character(), Creature::get_speed(), towing_data::get_towed(), Creature::has_effect(), has_engine_type(), in_deep_water, vehicle_part::info(), is_flying, is_flying_in_air(), is_moving(), is_rotorcraft(), is_towing(), is_watercraft(), k_traction(), ammo_effects::load(), m_bad, m_info, max(), max_reverse_velocity(), max_velocity(), min(), n_gettext, name, noise_and_smoke(), parts, player_in_control(), requested_z_change, rng(), sgn(), skidding, smart_controller_handle_turn(), stop(), strain(), total_power(), tow_data, turn_dir, valid_wheel_config(), and velocity.

Referenced by gain_moves(), pldrive(), and selfdrive().

◆ toggle_autopilot()

void vehicle::toggle_autopilot ( )

Definition at line 495 of file vehicle_use.cpp.

496 {
497  veh_menu menu( this, _( "Choose action for the autopilot" ) );
498 
499  menu.add( _( "Patrol…" ) )
500  .hotkey( "CONTROL_AUTOPILOT_PATROL" )
501  .desc( _( "Program the autopilot to patrol a nearby vehicle patrol zone. If no zones are nearby, you will be prompted to create one." ) )
502  .on_submit( [this] {
504  } );
505 
506  menu.add( _( "Follow…" ) )
507  .hotkey( "CONTROL_AUTOPILOT_FOLLOW" )
508  .desc( _( "Program the autopilot to follow you. It might be a good idea to have a remote control available to tell it to stop, too." ) )
509  .on_submit( [this] {
510  autopilot_on = true;
511  is_following = true;
512  is_patrolling = false;
513  if( !engine_on )
514  {
515  start_engines();
516  }
517  } );
518 
519  menu.add( _( "Stop…" ) )
520  .hotkey( "CONTROL_AUTOPILOT_STOP" )
521  .desc( _( "Stop all autopilot related activities." ) )
522  .on_submit( [this] {
523  autopilot_on = false;
524  is_patrolling = false;
525  is_following = false;
527  add_msg( _( "You turn the engine off." ) );
528  stop_engines();
529  } );
530 
531  menu.add( precollision_on ? _( "Disable pre-collision system" ) :
532  _( "Enable pre-collision system" ) )
533  .hotkey( "CONTROL_AUTOPILOT_CAS" )
534  .desc( _( "Toggle pre-collision system" ) )
535  .on_submit( [this] {
537  add_msg( precollision_on ? _( "You turn on pre-collision system." ) : _( "You turn off pre-collision system." ) );
538  } );
539 
540  menu.query();
541 }
void autopilot_patrol_check()

References _, veh_menu::add(), add_msg(), autodrive_local_target, autopilot_on, autopilot_patrol_check(), veh_menu_item::desc(), engine_on, veh_menu_item::hotkey(), is_following, is_patrolling, veh_menu_item::on_submit(), precollision_on, veh_menu::query(), start_engines(), stop_engines(), and tripoint_zero.

Referenced by build_interact_menu().

◆ toggle_tracking()

void vehicle::toggle_tracking ( )

Definition at line 543 of file vehicle_use.cpp.

544 {
545  if( tracking_on ) {
547  tracking_on = false;
548  add_msg( _( "You stop keeping track of the vehicle position." ) );
549  } else {
550  overmap_buffer.add_vehicle( this );
551  tracking_on = true;
552  add_msg( _( "You start keeping track of this vehicle's position." ) );
553  }
554 }
void add_vehicle(vehicle *veh)
Add the vehicle to be tracked in the overmap.
void remove_vehicle(const vehicle *veh)
Remove the vehicle from being tracked in the overmap.

References _, add_msg(), overmapbuffer::add_vehicle(), overmap_buffer, overmapbuffer::remove_vehicle(), and tracking_on.

Referenced by build_interact_menu(), game::place_vehicle_nearby(), remove_carried_vehicle(), and vehicle_unfolding_activity_actor::unfold_vehicle().

◆ tool_ammo_available()

std::pair< const itype_id &, int > vehicle::tool_ammo_available ( const itype_id tool_type) const

if tool is not an itype with tool != nullptr this returns { itype::NULL_ID(), 0 } pair

Parameters
toolthe item to examine
Returns
a pair of tool's first ammo type and the amount of it available from tanks / batteries

Definition at line 1724 of file vehicle_use.cpp.

1725 {
1726  if( !tool_type->tool ) {
1727  return { itype_id::NULL_ID(), 0 };
1728  }
1729  const itype_id &ft = tool_type->tool_slot_first_ammo();
1730  if( ft.is_null() ) {
1731  return { itype_id::NULL_ID(), 0 };
1732  }
1733  // 2 bil ought to be enough for everyone, and hopefully not overflow int
1734  const int64_t max = 2'000'000'000;
1735  if( ft->ammo->type == ammo_battery ) {
1736  return { ft, static_cast<int>( std::min<int64_t>( battery_left(), max ) ) };
1737  } else {
1738  return { ft, static_cast<int>( std::min<int64_t>( fuel_left( ft ), max ) ) };
1739  }
1740 }
const itype_id & tool_slot_first_ammo() const
Definition: itype.cpp:416
cata::value_ptr< islot_tool > tool
Slots for various item type properties.
Definition: itype.h:1197

References itype::ammo, ammo_battery, battery_left(), fuel_left(), string_id< T >::is_null(), max(), string_id< itype >::NULL_ID(), itype::tool, and itype::tool_slot_first_ammo().

Referenced by prepare_tool(), and use_vehicle_tool().

◆ total_accessory_epower()

units::power vehicle::total_accessory_epower ( ) const

Definition at line 4998 of file vehicle.cpp.

4999 {
5000  units::power epower = 0_W;
5001  for( int part : accessories ) {
5002  const vehicle_part &vp = parts[part];
5003  if( vp.enabled ) {
5004  epower += vp.info().epower;
5005  }
5006  }
5007  return epower;
5008 }

References accessories, vehicle_part::enabled, vpart_info::epower, vehicle_part::info(), part(), and parts.

Referenced by veh_app_interact::draw_info(), net_battery_charge_rate(), and power_parts().

◆ total_alternator_epower()

units::power vehicle::total_alternator_epower ( ) const

Definition at line 5063 of file vehicle.cpp.

5064 {
5065  if( !engine_on ) {
5066  return 0_W;
5067  }
5068  units::power epower = 0_W;
5069  for( const int p : alternators ) {
5070  const vehicle_part &vp = parts[p];
5071  if( is_alternator_on( vp ) ) {
5072  epower += part_epower( vp );
5073  }
5074  }
5075  return epower;
5076 }
bool is_alternator_on(const vehicle_part &vp) const
Definition: vehicle.cpp:1020

References alternators, engine_on, is_alternator_on(), part_epower(), and parts.

Referenced by veh_app_interact::draw_info(), net_battery_charge_rate(), and power_parts().

◆ total_engine_epower()

units::power vehicle::total_engine_epower ( ) const

Definition at line 5078 of file vehicle.cpp.

5079 {
5080  if( !engine_on ) {
5081  return 0_W;
5082  }
5083  // Engines: can both produce (plasma) or consume (gas, diesel) epower.
5084  // Gas engines require epower to run for ignition system, ECU, etc.
5085  // Electric motor consumption not included, see @ref vpart_info::energy_consumption
5086  units::power epower = 0_W;
5087  for( const int p : engines ) {
5088  const vehicle_part &vp = parts[p];
5089  if( is_engine_on( vp ) ) {
5090  epower += part_epower( vp );
5091  }
5092  }
5093  return epower;
5094 }

References engine_on, engines, is_engine_on(), part_epower(), and parts.

Referenced by net_battery_charge_rate(), and power_parts().

◆ total_mass()

units::mass vehicle::total_mass ( ) const

Definition at line 3472 of file vehicle.cpp.

3473 {
3474  // local_center_of_mass() is more frequently called
3475  // than rotated_center_of_mass().
3476  // To improve performance, refresh mass_center_no_precalc.
3477  if( mass_dirty ) {
3478  calc_mass_center( false );
3479  }
3480 
3481  return mass_cache;
3482 }

References calc_mass_center(), mass_cache, and mass_dirty.

Referenced by coeff_rolling_drag(), coeff_water_drag(), veh_interact::display_stats(), get_folded_item(), game::grabbed_veh_move(), ground_acceleration(), has_sufficient_rotorlift(), jack_quality(), k_traction(), lift_strength(), map::move_vehicle(), part_collision(), Character::pause(), rotor_acceleration(), monster::shove_vehicle(), slowdown(), map::vehicle_vehicle_collision(), and water_acceleration().

◆ total_power()

units::power vehicle::total_power ( bool  fueled = true,
bool  safe = false 
) const

Definition at line 3697 of file vehicle.cpp.

3698 {
3699  units::power pwr = 0_W;
3700  int count = 0;
3701 
3702  for( const int p : engines ) {
3703  const vehicle_part &vp = parts[p];
3704  if( is_engine_on( vp ) && ( !fueled || engine_fuel_left( vp ) ) ) {
3705  int m2c = safe ? vp.info().engine_info->m2c : 100;
3706  if( vp.has_fault_flag( "REDUCE_ENG_POWER" ) ) {
3707  m2c *= 0.6;
3708  }
3709  pwr += part_vpower_w( vp ) * m2c / 100;
3710  count++;
3711  }
3712  }
3713 
3714  for( const int p : alternators ) {
3715  const vehicle_part &vp = parts[p];
3716  if( is_alternator_on( vp ) ) {
3717  pwr += part_vpower_w( vp ); // alternators have negative power
3718  }
3719  }
3720  pwr = std::max( 0_W, pwr );
3721 
3722  if( count > 1 ) {
3723  pwr = pwr * 4 / ( 4 + count - 1 );
3724  }
3725  return pwr;
3726 }

References alternators, engine_fuel_left(), vpart_info::engine_info, engines, vehicle_part::has_fault_flag(), vehicle_part::info(), is_alternator_on(), is_engine_on(), max(), part_vpower_w(), parts, and iexamine::safe().

Referenced by veh_interact::calc_overview(), crash_terrain_around(), ground_acceleration(), idle(), lift_thrust_of_rotorcraft(), max_ground_velocity(), max_water_velocity(), safe_ground_velocity(), safe_water_velocity(), thrust(), and water_acceleration().

◆ total_solar_epower()

units::power vehicle::total_solar_epower ( ) const

Definition at line 5096 of file vehicle.cpp.

5097 {
5098  units::power epower = 0_W;
5099  map &here = get_map();
5100  for( const int p : solar_panels ) {
5101  const vehicle_part &vp = parts[p];
5102  const tripoint pos = global_part_pos3( vp );
5103  if( vp.is_unavailable() || !is_sm_tile_outside( here.getabs( pos ) ) ) {
5104  continue;
5105  }
5106 
5107  epower += part_epower( vp );
5108  }
5109  // Weather doesn't change much across the area of the vehicle, so just
5110  // sample it once.
5113  return epower * intensity;
5114 }
float max_sun_irradiance()
Definition: calendar.cpp:52
float incident_sun_irradiance(const weather_type_id &wtype, const time_point &t)
Definition: weather.cpp:143
weather_type_id current_weather(const tripoint_abs_ms &location, const time_point &t)
Definition: weather.cpp:176
static bool is_sm_tile_outside(const tripoint &real_global_pos)
Definition: vehicle.cpp:7854

References current_weather(), get_map(), map::getabs(), global_part_pos3(), global_square_location(), incident_sun_irradiance(), intensity, is_sm_tile_outside(), vehicle_part::is_unavailable(), max_sun_irradiance(), part_epower(), parts, pos, solar_panels, and calendar::turn.

Referenced by veh_app_interact::draw_info(), and net_battery_charge_rate().

◆ total_water_wheel_epower()

units::power vehicle::total_water_wheel_epower ( ) const

Definition at line 5140 of file vehicle.cpp.

5141 {
5142  units::power epower = 0_W;
5143  map &here = get_map();
5144  for( const int p : water_wheels ) {
5145  const vehicle_part &vp = parts[p];
5146  const tripoint pos = global_part_pos3( vp );
5147  if( vp.is_unavailable() || !is_sm_tile_over_water( here.getabs( pos ) ) ) {
5148  continue;
5149  }
5150 
5151  epower += part_epower( vp );
5152  }
5153  // TODO: river current intensity changes power - flat for now.
5154  return epower;
5155 }
static bool is_sm_tile_over_water(const tripoint &real_global_pos)
Definition: vehicle.cpp:7832

References get_map(), map::getabs(), global_part_pos3(), is_sm_tile_over_water(), vehicle_part::is_unavailable(), part_epower(), parts, pos, and water_wheels.

Referenced by veh_app_interact::draw_info(), net_battery_charge_rate(), and update_time().

◆ total_wind_epower()

units::power vehicle::total_wind_epower ( ) const

Definition at line 5116 of file vehicle.cpp.

5117 {
5118  map &here = get_map();
5119  const oter_id &cur_om_ter = overmap_buffer.ter( global_omt_location() );
5121  const w_point weatherPoint = *weather.weather_precise;
5122  units::power epower = 0_W;
5123  for( const int p : wind_turbines ) {
5124  const vehicle_part &vp = parts[p];
5125  const tripoint pos = global_part_pos3( vp );
5126  if( vp.is_unavailable() || !is_sm_tile_outside( here.getabs( pos ) ) ) {
5127  continue;
5128  }
5129 
5130  int windpower = get_local_windpower( weather.windspeed, cur_om_ter, here.getglobal( pos ),
5131  weather.winddirection, false );
5132  if( windpower <= ( weather.windspeed / 10.0 ) ) {
5133  continue;
5134  }
5135  epower += part_epower( vp ) * windpower;
5136  }
5137  return epower;
5138 }
tripoint_abs_ms getglobal(const tripoint &p) const
Definition: map.cpp:9625
const oter_id & ter(const tripoint_abs_omt &p)
Returns the overmap terrain at the given OMT coordinates.
tripoint_abs_omt global_omt_location() const
Definition: vehicle.cpp:3426
int get_local_windpower(int windpower, const oter_id &omter, const tripoint_abs_ms &location, const int &winddirection, bool sheltered)
Definition: weather.cpp:786

References get_local_windpower(), get_map(), get_weather(), map::getabs(), map::getglobal(), global_omt_location(), global_part_pos3(), is_sm_tile_outside(), vehicle_part::is_unavailable(), overmap_buffer, part_epower(), parts, pos, overmapbuffer::ter(), and wind_turbines.

Referenced by veh_app_interact::draw_info(), net_battery_charge_rate(), and update_time().

◆ tow_cable_too_far()

bool vehicle::tow_cable_too_far ( ) const

Definition at line 6886 of file vehicle.cpp.

6887 {
6888  if( !tow_data.get_towed_by() ) {
6889  debugmsg( "checking tow cable length on a vehicle that has no towing vehicle" );
6890  return false;
6891  }
6892  int index = get_tow_part();
6893  if( index == -1 ) {
6894  debugmsg( "towing data exists but no towing part" );
6895  return false;
6896  }
6897  map &here = get_map();
6898  tripoint towing_point = here.getabs( global_part_pos3( index ) );
6899  if( !tow_data.get_towed_by()->tow_data.get_towed() ) {
6900  debugmsg( "vehicle %s has data for a towing vehicle, but that towing vehicle does not have %s listed as towed",
6901  disp_name(), disp_name() );
6902  return false;
6903  }
6904  int other_index = tow_data.get_towed_by()->get_tow_part();
6905  if( other_index == -1 ) {
6906  debugmsg( "towing data exists but no towing part" );
6907  return false;
6908  }
6909  tripoint towed_point = here.getabs( tow_data.get_towed_by()->global_part_pos3( other_index ) );
6910  if( towing_point == tripoint_zero || towed_point == tripoint_zero ) {
6911  debugmsg( "towing data exists but no towing part" );
6912  return false;
6913  }
6914  return rl_dist( towing_point, towed_point ) >= 25;
6915 }

References debugmsg, disp_name(), get_map(), get_tow_part(), towing_data::get_towed(), towing_data::get_towed_by(), map::getabs(), global_part_pos3(), rl_dist(), tow_data, and tripoint_zero.

Referenced by map::move_vehicle().

◆ transform_terrain()

void vehicle::transform_terrain ( )

Definition at line 992 of file vehicle_use.cpp.

993 {
994  map &here = get_map();
995  for( const vpart_reference &vp : get_enabled_parts( "TRANSFORM_TERRAIN" ) ) {
996  const tripoint start_pos = vp.pos();
997  const vpslot_terrain_transform &ttd = *vp.info().transform_terrain_info;
998  bool prereq_fulfilled = false;
999  for( const std::string &flag : ttd.pre_flags ) {
1000  if( here.has_flag( flag, start_pos ) ) {
1001  prereq_fulfilled = true;
1002  break;
1003  }
1004  }
1005  if( prereq_fulfilled ) {
1006  const ter_id new_ter = ter_id( ttd.post_terrain );
1007  if( new_ter != ter_str_id::NULL_ID() ) {
1008  here.ter_set( start_pos, new_ter );
1009  }
1010  const furn_id new_furn = furn_id( ttd.post_furniture );
1011  if( new_furn != furn_str_id::NULL_ID() ) {
1012  here.furn_set( start_pos, new_furn );
1013  }
1015  if( new_field.id() ) {
1016  here.add_field( start_pos, new_field, ttd.post_field_intensity, ttd.post_field_age );
1017  }
1018  } else {
1019  const int speed = std::abs( velocity );
1020  int v_damage = rng( 3, speed );
1021  damage( here, vp.part_index(), v_damage, damage_bash, false );
1022  sounds::sound( start_pos, v_damage, sounds::sound_t::combat, _( "Clanggggg!" ), false,
1023  "smash_success", "hit_vehicle" );
1024  }
1025  }
1026 }
bool add_field(const tripoint &p, const field_type_id &type_id, int intensity=INT_MAX, const time_duration &age=0_turns, bool hit_player=true)
Add field entry at point, or set intensity if present.
Definition: map.cpp:6563
bool ter_set(const tripoint &p, const ter_id &new_terrain, bool avoid_creatures=false)
Definition: map.cpp:2226
std::string post_furniture
Definition: veh_type.h:166
std::string post_terrain
Definition: veh_type.h:165
time_duration post_field_age
Definition: veh_type.h:169
std::string post_field
Definition: veh_type.h:167

References _, abs(), map::add_field(), sounds::combat, damage(), damage_bash, field_type_id, furn_id, map::furn_set(), get_enabled_parts(), get_map(), map::has_flag(), string_id< furn_t >::NULL_ID(), string_id< ter_t >::NULL_ID(), vpslot_terrain_transform::post_field, vpslot_terrain_transform::post_field_age, vpslot_terrain_transform::post_field_intensity, vpslot_terrain_transform::post_furniture, vpslot_terrain_transform::post_terrain, vpslot_terrain_transform::pre_flags, rng(), sounds::sound(), speed, ter_id, map::ter_set(), and velocity.

Referenced by on_move().

◆ turn()

void vehicle::turn ( units::angle  deg)

Definition at line 668 of file vehicle_move.cpp.

669 {
670  if( deg == 0_degrees ) {
671  return;
672  }
673  if( velocity < 0 && !::get_option<bool>( "REVERSE_STEERING" ) ) {
674  deg = -deg;
675  }
676  last_turn = deg;
677  turn_dir = normalize( turn_dir + deg );
678  // quick rounding the turn dir to a multiple of 15
680 }

References last_turn, normalize(), round_to_multiple_of(), vehicles::steer_increment, turn_dir, and velocity.

Referenced by act_on_map(), game::grabbed_veh_move(), handbrake(), map::move_vehicle(), MapExtras::mx_helicopter(), part_collision(), pldrive(), restore_folded_parts(), and selfdrive().

◆ turret_query() [1/2]

turret_data vehicle::turret_query ( const tripoint pos)

Definition at line 68 of file turret.cpp.

69 {
70  auto res = get_parts_at( pos, "TURRET", part_status_flag::any );
71  return !res.empty() ? turret_query( *res.front() ) : turret_data();
72 }

References any, get_parts_at(), pos, and turret_query().

◆ turret_query() [2/2]

turret_data vehicle::turret_query ( vehicle_part pt)

Get firing data for a turret.

Definition at line 60 of file turret.cpp.

61 {
62  if( !pt.is_turret() || pt.removed || pt.is_broken() ) {
63  return turret_data();
64  }
65  return turret_data( this, &pt );
66 }
bool is_turret() const
Can this part function as a turret?

References vehicle_part::is_broken(), vehicle_part::is_turret(), and vehicle_part::removed.

Referenced by automatic_fire_turret(), build_interact_menu(), find_all_ready_turrets(), idle(), turret_data::in_range(), target_handler::mode_turrets(), turret_query(), turrets_aim(), turrets_aim_and_fire(), turrets_aim_and_fire_single(), and target_ui::update_turrets_in_range().

◆ turrets() [1/2]

std::vector< vehicle_part * > vehicle::turrets ( )

Get all vehicle turrets (excluding any that are destroyed)

Definition at line 36 of file turret.cpp.

37 {
38  std::vector<vehicle_part *> res;
39 
40  for( int index : turret_locations ) {
41  vehicle_part &e = parts[index];
42  if( !e.is_broken() && e.is_turret() ) {
43  res.push_back( &e );
44  }
45  }
46  return res;
47 }

References vehicle_part::is_broken(), vehicle_part::is_turret(), parts, and turret_locations.

Referenced by find_all_ready_turrets(), gain_moves(), idle(), turrets(), turrets_aim(), turrets_aim_and_fire(), turrets_aim_and_fire_all_manual(), turrets_aim_and_fire_single(), turrets_override_automatic_aim(), turrets_set_mode(), and turrets_set_targeting().

◆ turrets() [2/2]

std::vector< vehicle_part * > vehicle::turrets ( const tripoint target)

Get all vehicle turrets loaded and ready to fire at target.

Definition at line 49 of file turret.cpp.

50 {
51  std::vector<vehicle_part *> res = turrets();
52  // exclude turrets not ready to fire or where target is out of range
53  res.erase( std::remove_if( res.begin(), res.end(), [&]( vehicle_part * e ) {
54  return turret_query( *e ).query() != turret_data::status::ready ||
55  rl_dist( global_part_pos3( *e ), target ) > e->base.gun_range();
56  } ), res.end() );
57  return res;
58 }

References turrets().

◆ turrets_aim()

bool vehicle::turrets_aim ( std::vector< vehicle_part * > &  turrets)
private
Intelligence speeds up aiming of vehicle turrets

Definition at line 401 of file turret.cpp.

402 {
403  // Clear existing targets
404  for( vehicle_part *t : turrets ) {
405  if( !turret_query( *t ) ) {
406  debugmsg( "Expected a valid vehicle turret" );
407  return false;
408  }
409  t->reset_target( global_part_pos3( *t ) );
410  }
411 
412  avatar &player_character = get_avatar();
413  if( player_character.has_trait( trait_BRAWLER ) ) {
414  player_character.add_msg_if_player(
415  _( "Pfft. You are a brawler; using turrets is beneath you." ) );
416  return false;
417  }
418 
419  // Get target
421  turrets );
422 
423  bool got_target = !trajectory.empty();
424  if( got_target ) {
425  tripoint target = trajectory.back();
426  // Set target for any turret in range
427  for( vehicle_part *t : turrets ) {
428  if( turret_query( *t ).in_range( target ) ) {
429  t->target.second = target;
430  }
431  }
432 
433  ///\EFFECT_INT speeds up aiming of vehicle turrets
434  player_character.set_moves( std::min( 0,
435  player_character.get_moves() - 100 + ( 5 * player_character.int_cur ) ) );
436  }
437  return got_target;
438 }
int int_cur
Definition: character.h:579
bool has_trait(const trait_id &b) const override
Returns true if the player has the entered trait.
Definition: mutation.cpp:111
Definition: avatar.h:84
bool in_range(const tripoint &target) const
Check if target is in range of this turret (considers current ammo) Assumes this turret's status is '...
Definition: turret.cpp:202
trajectory mode_turrets(avatar &you, vehicle &veh, const std::vector< vehicle_part * > &turrets)
Selecting target for turrets (when using vehicle controls)
Definition: ranged.cpp:481
std::vector< tripoint > trajectory
Definition: ranged.h:29
static const trait_id trait_BRAWLER("BRAWLER")

References _, Character::add_msg_if_player(), debugmsg, get_avatar(), Creature::get_moves(), global_part_pos3(), Character::has_trait(), turret_data::in_range(), Character::int_cur, min(), target_handler::mode_turrets(), Creature::set_moves(), trait_BRAWLER, turret_query(), and turrets().

Referenced by turrets_aim_and_fire(), and turrets_override_automatic_aim().

◆ turrets_aim_and_fire()

int vehicle::turrets_aim_and_fire ( std::vector< vehicle_part * > &  turrets)
private

Definition at line 384 of file turret.cpp.

385 {
386  int shots = 0;
387  if( turrets_aim( turrets ) ) {
388  for( vehicle_part *t : turrets ) {
389  bool has_target = t->target.first != t->target.second;
390  if( has_target ) {
391  turret_data turret = turret_query( *t );
392  npc &cpu = t->get_targeting_npc( *this );
393  shots += turret.fire( cpu, t->target.second );
394  t->reset_target( global_part_pos3( *t ) );
395  }
396  }
397  }
398  return shots;
399 }
int fire(Character &c, const tripoint &target)
Fire the turret's gun at a given target.
Definition: turret.cpp:311
bool turrets_aim(std::vector< vehicle_part * > &turrets)
Definition: turret.cpp:401

References turret_data::fire(), global_part_pos3(), turret_query(), turrets(), and turrets_aim().

Referenced by turrets_aim_and_fire_all_manual(), and turrets_aim_and_fire_single().

◆ turrets_aim_and_fire_all_manual()

bool vehicle::turrets_aim_and_fire_all_manual ( bool  show_msg = false)

Definition at line 355 of file turret.cpp.

356 {
357  std::vector<vehicle_part *> turrets = find_all_ready_turrets( true, false );
358 
359  if( turrets.empty() ) {
360  if( show_msg ) {
362  _( "Can't aim turrets: all turrets are offline or set to automatic targeting mode." ) );
363  }
364  return false;
365  }
366 
368  return true;
369 }
int turrets_aim_and_fire(std::vector< vehicle_part * > &turrets)
Definition: turret.cpp:384
std::vector< vehicle_part * > find_all_ready_turrets(bool manual, bool automatic)
Definition: turret.cpp:440

References _, add_msg(), find_all_ready_turrets(), m_warning, turrets(), and turrets_aim_and_fire().

Referenced by build_interact_menu().

◆ turrets_aim_and_fire_single()

void vehicle::turrets_aim_and_fire_single ( )

Select a single ready turret, aim it using the aiming UI and fire.

Definition at line 325 of file turret.cpp.

326 {
327  std::vector<std::string> option_names;
328  std::vector<vehicle_part *> options;
329 
330  // Find all turrets that are ready to fire
331  for( vehicle_part *&t : turrets() ) {
332  turret_data data = turret_query( *t );
333  if( data.query() == turret_data::status::ready ) {
334  option_names.push_back( t->name() );
335  options.push_back( t );
336  }
337  }
338 
339  // Select one
340  if( options.empty() ) {
341  add_msg( m_warning, _( "None of the turrets are ready to fire." ) );
342  return;
343  }
344  const int idx = uilist( _( "Aim which turret?" ), option_names );
345  if( idx < 0 ) {
346  return;
347  }
348  vehicle_part *turret = options[idx];
349 
350  std::vector<vehicle_part *> turrets;
351  turrets.push_back( turret );
353 }
bool empty() const
Definition: cata_path.h:123
uilist: scrolling vertical list menu
Definition: ui.h:232
cata_path options()
Definition: path_info.cpp:354

References _, add_msg(), cata_path::empty(), m_warning, PATH_INFO::options(), turret_data::query(), turret_data::ready, turret_query(), turrets(), and turrets_aim_and_fire().

Referenced by build_interact_menu().

◆ turrets_override_automatic_aim()

void vehicle::turrets_override_automatic_aim ( )

Set target for automatic turrets using the aiming UI.

Definition at line 371 of file turret.cpp.

372 {
373  std::vector<vehicle_part *> turrets = find_all_ready_turrets( false, true );
374 
375  if( turrets.empty() ) {
377  _( "Can't aim turrets: all turrets are offline or set to manual targeting mode." ) );
378  return;
379  }
380 
381  turrets_aim( turrets );
382 }

References _, add_msg(), find_all_ready_turrets(), m_warning, turrets(), and turrets_aim().

Referenced by build_interact_menu().

◆ turrets_set_mode()

void vehicle::turrets_set_mode ( )

Set firing mode for specific turrets.

Definition at line 509 of file turret.cpp.

510 {
511  std::vector<vehicle_part *> turrets;
512  std::vector<tripoint> locations;
513 
514  for( vehicle_part &p : parts ) {
515  if( p.base.is_gun() ) {
516  turrets.push_back( &p );
517  locations.push_back( global_part_pos3( p ) );
518  }
519  }
520 
521  pointmenu_cb callback( locations );
522 
523  int sel = 0;
524  while( true ) {
525  uilist menu;
526  menu.text = _( "Set turret firing modes" );
527  menu.callback = &callback;
528  menu.selected = sel;
529  menu.fselected = sel;
530  menu.w_y_setup = 2;
531 
532  for( vehicle_part *&p : turrets ) {
533  menu.addentry( -1, true, MENU_AUTOASSIGN, "%s [%s]",
534  p->name(), p->base.gun_current_mode().tname() );
535  }
536 
537  menu.query();
538  if( menu.ret < 0 || static_cast<size_t>( menu.ret ) >= turrets.size() ) {
539  break;
540  }
541 
542  sel = menu.ret;
543  turrets[ sel ]->base.gun_cycle_mode();
544  }
545 }
Callback for uilist that pairs menu entries with points When an entry is selected,...
Definition: ui.h:576
int ret
Definition: ui.h:525
void addentry(const std::string &txt)
Definition: ui.cpp:1210
int fselected
Definition: ui.h:490
int selected
Definition: ui.h:526
uilist_callback * callback
Definition: ui.h:434
pos_scalar w_y_setup
Definition: ui.h:437
std::string text
Definition: ui.h:419
void query(bool loop=true, int timeout=-1)
Handle input and update display.
Definition: ui.cpp:1032
generic_factory< overmap_location > locations("overmap location")
const int MENU_AUTOASSIGN
Definition: ui.h:38

References _, uilist::addentry(), uilist::callback, uilist::fselected, global_part_pos3(), anonymous_namespace{overmap_location.cpp}::locations, MENU_AUTOASSIGN, parts, uilist::query(), uilist::ret, uilist::selected, uilist::text, turrets(), and uilist::w_y_setup.

Referenced by build_interact_menu().

◆ turrets_set_targeting()

void vehicle::turrets_set_targeting ( )

Set targeting mode for specific turrets.

Definition at line 453 of file turret.cpp.

454 {
455  std::vector<vehicle_part *> turrets;
456  std::vector<tripoint> locations;
457 
458  for( vehicle_part &p : parts ) {
459  if( p.is_turret() ) {
460  turrets.push_back( &p );
461  locations.push_back( global_part_pos3( p ) );
462  }
463  }
464 
465  pointmenu_cb callback( locations );
466 
467  int sel = 0;
468  while( true ) {
469  uilist menu;
470  menu.text = _( "Set turret targeting" );
471  menu.callback = &callback;
472  menu.selected = sel;
473  menu.fselected = sel;
474  menu.w_y_setup = 2;
475 
476  for( vehicle_part *&p : turrets ) {
477  menu.addentry( -1, has_part( global_part_pos3( *p ), "TURRET_CONTROLS" ), MENU_AUTOASSIGN,
478  "%s [%s]", p->name(), p->enabled ?
479  _( "auto -> manual" ) : has_part( global_part_pos3( *p ), "TURRET_CONTROLS" ) ?
480  _( "manual -> auto" ) :
481  _( "manual (turret control unit required for auto mode)" ) );
482  }
483 
484  menu.query();
485  if( menu.ret < 0 || static_cast<size_t>( menu.ret ) >= turrets.size() ) {
486  break;
487  }
488 
489  sel = menu.ret;
490  if( has_part( locations[ sel ], "TURRET_CONTROLS" ) ) {
491  turrets[sel]->enabled = !turrets[sel]->enabled;
492  } else {
493  turrets[sel]->enabled = false;
494  }
495 
496  for( const vpart_reference &vp : get_avail_parts( "TURRET_CONTROLS" ) ) {
497  vehicle_part &e = vp.part();
498  if( e.mount == turrets[sel]->mount ) {
499  e.enabled = turrets[sel]->enabled;
500  }
501  }
502 
503  // clear the turret's current targets to prevent unwanted auto-firing
504  tripoint pos = locations[ sel ];
505  turrets[ sel ]->reset_target( pos );
506  }
507 }

References _, uilist::addentry(), uilist::callback, vehicle_part::enabled, uilist::fselected, get_avail_parts(), global_part_pos3(), has_part(), anonymous_namespace{overmap_location.cpp}::locations, MENU_AUTOASSIGN, vehicle_part::mount, parts, pos, uilist::query(), uilist::ret, uilist::selected, uilist::text, turrets(), and uilist::w_y_setup.

Referenced by build_interact_menu().

◆ unboard_all()

void vehicle::unboard_all ( ) const

Definition at line 7134 of file vehicle.cpp.

7135 {
7136  map &here = get_map();
7137  std::vector<int> bp = boarded_parts();
7138  for( const int &i : bp ) {
7139  here.unboard_vehicle( global_part_pos3( i ) );
7140  }
7141 }
void unboard_vehicle(const vpart_reference &, Character *passenger, bool dead_passenger=false)
Definition: map.cpp:1395
bodypart_id bp
Definition: creature.h:238

References boarded_parts(), bp, get_map(), global_part_pos3(), and map::unboard_vehicle().

Referenced by act_on_map(), and vehicle_folding_activity_actor::fold_vehicle().

◆ unfolding_time()

time_duration vehicle::unfolding_time ( ) const

Definition at line 7616 of file vehicle.cpp.

7617 {
7618  const vehicle_part_range vpr = get_all_parts();
7619  return std::accumulate( vpr.begin(), vpr.end(), time_duration(),
7620  []( time_duration & acc, const vpart_reference & part ) {
7621  return acc + ( part.part().removed ? time_duration() : part.info().get_unfolding_time() );
7622  } );
7623 }
time_duration get_unfolding_time() const
Definition: veh_type.cpp:1151

References generic_vehicle_part_range< range_type >::begin(), generic_vehicle_part_range< range_type >::end(), get_all_parts(), vpart_info::get_unfolding_time(), vehicle_part::info(), and part().

Referenced by get_folded_item().

◆ unlink_cables()

void vehicle::unlink_cables ( const point mount,
Character remover,
bool  unlink_items = false,
bool  unlink_tow_cables = false,
bool  unlink_power_cords = false 
)

Disconnect cables attached to the specified mount point.

Parameters
mountThe mount point to detach cables from.
removerThe character disconnecting the cables.
unlink_itemsIf extension cord and device items should be unlinked.
unlink_tow_cablesIf tow cables should be unlinked.
unlink_power_cordsIf power grid cables (power_cord) should be unlinked.

Definition at line 7025 of file vehicle.cpp.

7027 {
7028  if( !unlink_items && !unlink_tow_cables && !unlink_power_cords ) {
7029  return;
7030  }
7031  for( const int index : parts_at_relative( mount, true, false ) ) {
7032  vehicle_part &part = parts[ index ];
7033 
7034  if( unlink_items && part.has_flag( vp_flag::linked_flag ) ) {
7038  remover.add_msg_if_player( _( "You detach items connected to the %s." ), part.name( false ) );
7039  }
7040  if( unlink_tow_cables && part.info().has_flag( "TOW_CABLE" ) ) {
7041  bool u_can_stash_tow = remover.can_stash( part.get_base() );
7042  invalidate_towing( true, &remover );
7043  if( u_can_stash_tow ) {
7044  remover.add_msg_if_player( _( "You detach the %s and take it." ), part.name( false ) );
7045  } else {
7046  remover.add_msg_if_player( _( "You detach the %s and drop it." ), part.name( false ) );
7047  }
7048  }
7049  if( unlink_power_cords && part.info().has_flag( VPFLAG_POWER_TRANSFER ) ) {
7050  item drop = part_to_item( part );
7051  bool u_can_stash = remover.can_stash( drop );
7052  if( !magic && !drop.has_flag( flag_NO_DROP ) && remover.i_add_or_drop( drop ) ) {
7053  if( u_can_stash ) {
7054  remover.add_msg_if_player( _( "You detach the %s and take it." ), drop.type_name() );
7055  } else {
7056  remover.add_msg_if_player( _( "You detach the %s and drop it." ), drop.type_name() );
7057  }
7058  } else {
7059  remover.add_msg_if_player( _( "You detached the %s." ), drop.type_name() );
7060  }
7062  remove_part( part );
7063  }
7064  }
7065 }
std::string type_name(unsigned int quantity=1, bool use_variant=true, bool use_cond_name=true, bool use_corpse=true) const
Name of the item type (not the item), with proper plural.
Definition: item.cpp:14449
time_point last_disconnected
Definition: vehicle.h:531

References _, Character::add_msg_if_player(), Character::can_stash(), flag_NO_DROP, vehicle_part::get_base(), item::has_flag(), vpart_info::has_flag(), vehicle_part::has_flag(), Character::i_add_or_drop(), vehicle_part::info(), invalidate_towing(), vehicle_part::last_disconnected, linked_flag, linked_item_epower_this_turn, magic, vehicle_part::name(), part(), part_to_item(), parts, parts_at_relative(), vehicle_part::remove_flag(), remove_part(), remove_remote_part(), calendar::turn, item::type_name(), and VPFLAG_POWER_TRANSFER.

Referenced by build_interact_menu(), veh_interact::complete_vehicle(), and separate_from_grid().

◆ unlock() [1/2]

void vehicle::unlock ( )

Definition at line 1051 of file vehicle.cpp.

1052 {
1053  is_locked = false;
1054  for( vehicle_part &vp : parts ) {
1055  if( vp.info().has_flag( "SECURITY" ) ) {
1056  vp.enabled = false;
1057  }
1058  if( vp.is_engine() ) {
1059  vp.base.faults.erase( fault_engine_immobiliser );
1060  }
1061  }
1062 }

References fault_engine_immobiliser, is_locked, and parts.

Referenced by open_or_close().

◆ unlock() [2/2]

void vehicle::unlock ( int  part_index)

Unlocks a lockable, closed part at the specified index.

If it's a multipart, unlocks all attached parts as well. Does not affect vehicle is_locked flag.

Parameters
part_indexThe index in the parts list of the part to unlock.

Definition at line 1225 of file vehicle_use.cpp.

1226 {
1227  vehicle_part &vp = part( part_index );
1228  if( !vp.info().has_flag( "LOCKABLE_DOOR" ) ) {
1229  debugmsg( "Attempted to unlock non-lockable part %d (%s) on a %s!", part_index, vp.name(), name );
1230  } else {
1231  lock_or_unlock( part_index, false );
1232  }
1233 }

References debugmsg, vpart_info::has_flag(), vehicle_part::info(), lock_or_unlock(), vehicle_part::name(), name, and part().

Referenced by game::place_vehicle_nearby(), and doors::unlock_door().

◆ update_active_fakes()

void vehicle::update_active_fakes ( )

Definition at line 2300 of file vehicle_move.cpp.

2301 {
2302  for( const int fake_index : fake_parts ) {
2303  vehicle_part &part_fake = parts.at( fake_index );
2304  if( part_fake.removed ) {
2305  continue;
2306  }
2307  const vehicle_part &part_real = parts.at( part_fake.fake_part_to );
2308  const tripoint &fake_precalc = part_fake.precalc[0];
2309  const tripoint &real_precalc = part_real.precalc[0];
2310  const vpart_edge_info &real_edge = edges[part_real.mount];
2311  const bool is_protrusion = part_real.info().has_flag( "PROTRUSION" );
2312 
2313  if( real_edge.forward != -1 ) {
2314  const tripoint &forward = parts.at( real_edge.forward ).precalc[0];
2315  part_fake.is_active_fake = should_enable_fake( fake_precalc, real_precalc, forward );
2316  }
2317  if( real_edge.back != -1 && ( !part_fake.is_active_fake || real_edge.forward == -1 ) ) {
2318  const tripoint &back = parts.at( real_edge.back ).precalc[0];
2319  part_fake.is_active_fake = should_enable_fake( fake_precalc, real_precalc, back );
2320  }
2321  if( is_protrusion && part_fake.fake_protrusion_on >= 0 ) {
2322  part_fake.is_active_fake = parts.at( part_fake.fake_protrusion_on ).is_active_fake;
2323  }
2324  }
2325 }
bool should_enable_fake(const tripoint &fake_precalc, const tripoint &parent_precalc, const tripoint &neighbor_precalc) const
int fake_protrusion_on
Definition: vehicle.h:574
bool is_active_fake
Definition: vehicle.h:572

References vpart_edge_info::back, edges, vehicle_part::fake_part_to, fake_parts, vehicle_part::fake_protrusion_on, vpart_edge_info::forward, vpart_info::has_flag(), vehicle_part::info(), vehicle_part::is_active_fake, vehicle_part::mount, parts, vehicle_part::precalc, vehicle_part::removed, and should_enable_fake().

Referenced by map::displace_vehicle(), and refresh().

◆ update_alternator_load()

void vehicle::update_alternator_load ( )

Definition at line 5205 of file vehicle.cpp.

5206 {
5207  if( !engine_on ) {
5208  alternator_load = 0;
5209  return;
5210  }
5211  units::power engine_vpower = 0_W;
5212  for( const int p : engines ) {
5213  const vehicle_part &vp = parts[p];
5214  if( is_engine_on( vp ) && vp.info().has_flag( "E_ALTERNATOR" ) ) {
5215  engine_vpower += part_vpower_w( vp );
5216  }
5217  }
5218 
5219  if( engine_vpower == 0_W ) {
5220  alternator_load = 0;
5221  return;
5222  }
5223 
5224  units::power alternators_power = 0_W;
5225  for( const int p : alternators ) {
5226  const vehicle_part &vp = parts[p];
5227  if( is_alternator_on( vp ) ) {
5228  alternators_power += part_vpower_w( vp );
5229  }
5230  }
5231  alternators_power += extra_drag;
5232 
5233  alternator_load = std::abs( 1000 * alternators_power / engine_vpower );
5234 }

References abs(), alternator_load, alternators, engine_on, engines, extra_drag, vpart_info::has_flag(), vehicle_part::info(), is_alternator_on(), is_engine_on(), part_vpower_w(), and parts.

Referenced by power_parts(), and smart_controller_handle_turn().

◆ update_time()

void vehicle::update_time ( const time_point update_to)

Definition at line 7876 of file vehicle.cpp.

7877 {
7878  const time_point update_from = last_update;
7879  if( update_to < update_from || update_from == time_point( 0 ) ) {
7880  // Special case going backwards in time - that happens
7881  last_update = update_to;
7882  return;
7883  }
7884 
7885  map &here = get_map();
7886 
7887  if( sm_pos.z < 0 ) {
7888  last_update = update_to;
7889  return;
7890  }
7891 
7892  if( update_to >= update_from && update_to - update_from < 1_minutes ) {
7893  // We don't need to check every turn
7894  return;
7895  }
7896  time_duration elapsed = update_to - last_update;
7897  last_update = update_to;
7898 
7899  // Weather stuff, only for z-levels >= 0
7900  // TODO: Have it wash cars from blood?
7901  if( funnels.empty() && solar_panels.empty() && wind_turbines.empty() && water_wheels.empty() ) {
7902  return;
7903  }
7904  // Get one weather data set per vehicle, they don't differ much across vehicle area
7905  const weather_sum accum_weather = sum_conditions( update_from, update_to,
7907  // make some reference objects to use to check for reload
7908  const item water( "water" );
7909  const item water_clean( "water_clean" );
7910 
7911  for( int idx : funnels ) {
7912  const vehicle_part &pt = parts[idx];
7913 
7914  // we need an unbroken funnel mounted on the exterior of the vehicle
7915  if( pt.is_unavailable() || !is_sm_tile_outside( here.getabs( global_part_pos3( pt ) ) ) ) {
7916  continue;
7917  }
7918 
7919  // we need an empty tank (or one already containing water) below the funnel
7920  auto tank = std::find_if( parts.begin(), parts.end(), [&]( const vehicle_part & e ) {
7921  return pt.mount == e.mount && e.is_tank() &&
7922  ( e.can_reload( water ) || e.can_reload( water_clean ) );
7923  } );
7924 
7925  if( tank == parts.end() ) {
7926  continue;
7927  }
7928 
7929  const double area_in_mm2 = std::pow( pt.info().bonus, 2 ) * M_PI;
7930  const int qty = roll_remainder( funnel_charges_per_turn( area_in_mm2, accum_weather.rain_amount ) );
7931  int c_qty = qty + ( tank->can_reload( water_clean ) ? tank->ammo_remaining() : 0 );
7932  int cost_to_purify = c_qty * itype_water_purifier->charges_to_use();
7933 
7934  if( qty > 0 ) {
7935  const std::optional<vpart_reference> vp_purifier = vpart_position( *this, idx )
7937 
7938  if( vp_purifier && ( fuel_left( itype_battery ) > cost_to_purify ) ) {
7939  tank->ammo_set( itype_water_clean, c_qty );
7940  discharge_battery( cost_to_purify );
7941  } else {
7942  tank->ammo_set( itype_water, tank->ammo_remaining() + qty );
7943  }
7944  invalidate_mass();
7945  }
7946  }
7947 
7948  if( !solar_panels.empty() ) {
7949  units::power epower = 0_W;
7950  for( const int p : solar_panels ) {
7951  const vehicle_part &vp = parts[p];
7952  const tripoint pos = global_part_pos3( vp );
7953  if( vp.is_unavailable() || !is_sm_tile_outside( here.getabs( pos ) ) ) {
7954  continue;
7955  }
7956  epower += part_epower( vp );
7957  }
7958  double intensity = accum_weather.radiant_exposure / max_sun_irradiance() / to_seconds<float>
7959  ( elapsed );
7960  int energy_bat = power_to_energy_bat( epower * intensity, elapsed );
7961  if( energy_bat > 0 ) {
7962  add_msg_debug( debugmode::DF_VEHICLE, "%s got %d kJ energy from solar panels", name, energy_bat );
7963  charge_battery( energy_bat );
7964  }
7965  }
7966  if( !wind_turbines.empty() ) {
7967  // TODO: use accum_weather wind data to backfill wind turbine
7968  // generation capacity.
7969  units::power epower = total_wind_epower();
7970  int energy_bat = power_to_energy_bat( epower, elapsed );
7971  if( energy_bat > 0 ) {
7972  add_msg_debug( debugmode::DF_VEHICLE, "%s got %d kJ energy from wind turbines", name, energy_bat );
7973  charge_battery( energy_bat );
7974  }
7975  }
7976  if( !water_wheels.empty() ) {
7978  int energy_bat = power_to_energy_bat( epower, elapsed );
7979  if( energy_bat > 0 ) {
7980  add_msg_debug( debugmode::DF_VEHICLE, "%s got %d kJ energy from water wheels", name, energy_bat );
7981  charge_battery( energy_bat );
7982  }
7983  }
7984 }
A point in the game time.
Definition: calendar.h:460
double funnel_charges_per_turn(const double surface_area_mm2, const double rain_depth_mm_per_hour)
Definition: weather.cpp:272
weather_sum sum_conditions(const time_point &start, const time_point &end, const tripoint_abs_ms &location)
Definition: weather.cpp:187
float radiant_exposure
Definition: weather.h:115
int rain_amount
Definition: weather.h:113
static const itype_id itype_water_clean("water_clean")
static const itype_id itype_water_purifier("water_purifier")
static const itype_id itype_water("water")

References add_msg_debug, vpart_info::bonus, charge_battery(), itype::charges_to_use(), debugmode::DF_VEHICLE, discharge_battery(), fuel_left(), funnel_charges_per_turn(), funnels, get_map(), map::getabs(), global_part_pos3(), global_square_location(), vehicle_part::info(), intensity, invalidate_mass(), is_sm_tile_outside(), vehicle_part::is_unavailable(), itype_battery, itype_water, itype_water_clean, itype_water_purifier, last_update, M_PI, max_sun_irradiance(), name, part_epower(), vpart_position::part_with_tool(), parts, pos, power_to_energy_bat(), weather_sum::radiant_exposure, weather_sum::rain_amount, roll_remainder(), sm_pos, solar_panels, sum_conditions(), total_water_wheel_epower(), total_wind_epower(), water, water_wheels, wind_turbines, and tripoint::z.

Referenced by idle().

◆ use_autoclave()

void vehicle::use_autoclave ( int  p)

Definition at line 1370 of file vehicle_use.cpp.

1371 {
1372  vehicle_part &vp = parts[p];
1373  vehicle_stack items = get_items( vp );
1374  bool filthy_items = std::any_of( items.begin(), items.end(), []( const item & i ) {
1375  return i.has_flag( json_flag_FILTHY );
1376  } );
1377 
1378  bool unpacked_items = std::any_of( items.begin(), items.end(), []( const item & i ) {
1379  return i.has_flag( STATIC( flag_id( "NO_PACKED" ) ) );
1380  } );
1381 
1382  bool cbms = std::all_of( items.begin(), items.end(), []( const item & i ) {
1383  return i.is_bionic();
1384  } );
1385 
1386  if( vp.enabled ) {
1387  vp.enabled = false;
1388  add_msg( m_bad,
1389  _( "You turn the autoclave off before it's finished the program, and open its door." ) );
1390  } else if( items.empty() ) {
1391  add_msg( m_bad, _( "The autoclave is empty; there's no point in starting it." ) );
1392  } else if( fuel_left( itype_water ) < 8 && fuel_left( itype_water_clean ) < 8 ) {
1393  add_msg( m_bad, _( "You need 8 charges of water in the tanks of the %s for the autoclave to run." ),
1394  name );
1395  } else if( filthy_items ) {
1396  add_msg( m_bad,
1397  _( "You need to remove all filthy items from the autoclave to start the sterilizing cycle." ) );
1398  } else if( !cbms ) {
1399  add_msg( m_bad, _( "Only CBMs can be sterilized in an autoclave." ) );
1400  } else if( unpacked_items ) {
1401  add_msg( m_bad, _( "You should put your CBMs in autoclave pouches to keep them sterile." ) );
1402  } else {
1403  vp.enabled = true;
1404  for( item &n : items ) {
1405  n.set_age( 0_turns );
1406  }
1407 
1408  if( fuel_left( itype_water ) >= 8 ) {
1409  drain( itype_water, 8 );
1410  } else {
1411  drain( itype_water_clean, 8 );
1412  }
1413 
1414  add_msg( m_good, _( "You turn the autoclave on and it starts its cycle." ) );
1415  }
1416 }
bool empty() const
Definition: item_stack.cpp:19

References _, add_msg(), item_stack::begin(), drain(), item_stack::empty(), vehicle_part::enabled, item_stack::end(), fuel_left(), get_items(), itype_water, itype_water_clean, m_bad, m_good, name, and parts.

◆ use_charges()

std::list< item > vehicle::use_charges ( const vpart_position vp,
const itype_id type,
int &  quantity,
const std::function< bool(const item &)> &  filter,
bool  in_tools = false 
)

Consumes specified charges (or fewer) from the vehicle part.

Parameters
whatspecific type of charge required, e.g. 'battery'
qtymaximum charges to consume. On return set to number of charges not found (or zero)
filterMust return true for use to occur.
Returns
items that provide consumed charges

Definition at line 7743 of file vehicle.cpp.

7745 {
7746  std::list<item> ret;
7747  // HACK: water_faucet pseudo tool gives access to liquids in tanks
7748  const itype_id veh_tool_type = type.obj().phase > phase_id::SOLID
7750  : type;
7751 
7752  if( const std::optional<vpart_reference> tool_vp = vp.part_with_tool( veh_tool_type ) ) {
7753  const itype_id &tool_fuel_type = type->tool_slot_first_ammo();
7754  // use the tool's ammo charges
7755  const itype_id &fuel_type = tool_fuel_type.is_null() ? type : tool_fuel_type;
7756  item tmp( type, calendar::turn_zero ); // TODO: add a sane birthday arg
7757  // TODO: Handle water poison when crafting starts respecting it
7758  tmp.charges = tool_vp->vehicle().drain( fuel_type, quantity );
7759  quantity -= tmp.charges;
7760  ret.push_back( tmp );
7761  add_msg_debug( debugmode::DF_VEHICLE, "drained %d %s from %s",
7762  tmp.charges, fuel_type.str(), tool_vp->vehicle().name );
7763 
7764  if( quantity == 0 ) {
7765  return ret;
7766  }
7767  }
7768 
7769  if( const std::optional<vpart_reference> cargo_vp = vp.cargo() ) {
7770  std::list<item> tmp = cargo_vp->items().use_charges( type, quantity, vp.pos(), filter, in_tools );
7771  ret.splice( ret.end(), tmp );
7772  if( quantity <= 0 ) {
7773  return ret;
7774  }
7775  }
7776 
7777  return ret;
7778 }
static const itype_id itype_water_faucet("water_faucet")

References add_msg_debug, vpart_position::cargo(), item::charges, debugmode::DF_VEHICLE, filter, string_id< T >::is_null(), itype_water_faucet, string_id< T >::obj(), vpart_position::part_with_tool(), vpart_position::pos(), cata::hash64_detail::ret, SOLID, string_id< T >::str(), calendar::turn_zero, and type.

◆ use_dishwasher()

void vehicle::use_dishwasher ( int  p)

Definition at line 1502 of file vehicle_use.cpp.

1503 {
1504  vehicle_part &vp = parts[p];
1505  avatar &player_character = get_avatar();
1506  bool detergent_is_enough = player_character.crafting_inventory().has_charges( itype_detergent, 5 );
1507  vehicle_stack items = get_items( vp );
1508  bool filthy_items = std::all_of( items.begin(), items.end(), []( const item & i ) {
1509  return i.has_flag( json_flag_FILTHY );
1510  } );
1511 
1512  std::string buffer;
1513  buffer += _( "Soft items can't be cleaned in a dishwasher; you should use a washing machine for that. You need to remove them:" );
1514  bool soft_items = false;
1515  for( const item &it : items ) {
1516  if( it.is_soft() ) {
1517  soft_items = true;
1518  buffer += " " + it.tname();
1519  }
1520  }
1521 
1522  if( vp.enabled ) {
1523  vp.enabled = false;
1524  add_msg( m_bad,
1525  _( "You turn the dishwasher off before it's finished its cycle, and open its lid." ) );
1526  } else if( items.empty() ) {
1527  add_msg( m_bad, _( "The dishwasher is empty, there's no point in starting it." ) );
1528  } else if( fuel_left( itype_water ) < 24 && fuel_left( itype_water_clean ) < 24 ) {
1529  add_msg( m_bad, _( "You need 24 charges of water in the tanks of the %s to fill the dishwasher." ),
1530  name );
1531  } else if( !detergent_is_enough ) {
1532  add_msg( m_bad, _( "You need 5 charges of a detergent for the dishwasher." ) );
1533  } else if( !filthy_items ) {
1534  add_msg( m_bad,
1535  _( "You need to remove all non-filthy items from the dishwasher to start the washing program." ) );
1536  } else if( soft_items ) {
1537  add_msg( m_bad, buffer );
1538  } else {
1539  vp.enabled = true;
1540  for( item &n : items ) {
1541  n.set_age( 0_turns );
1542  }
1543 
1544  if( fuel_left( itype_water ) >= 24 ) {
1545  drain( itype_water, 24 );
1546  } else {
1547  drain( itype_water_clean, 24 );
1548  }
1549 
1550  std::vector<item_comp> detergent;
1551  detergent.emplace_back( itype_detergent, 5 );
1552  player_character.consume_items( detergent, 1, is_crafting_component );
1553 
1554  add_msg( m_good,
1555  _( "You pour some detergent into the dishwasher, close its lid, and turn it on. The dishwasher is being filled from the water tanks." ) );
1556  }
1557 }
std::list< item > consume_items(const comp_selection< item_comp > &is, int batch, const std::function< bool(const item &)> &filter=return_true< item >, bool select_ind=false)
Definition: crafting.cpp:2029
virtual bool has_charges(const itype_id &it, int quantity, const std::function< bool(const item &)> &filter=return_true< item >) const
Definition: visitable.cpp:223
bool is_crafting_component(const item &component)
Default filter for crafting component searches.
Definition: item.h:3267
static const itype_id itype_detergent("detergent")

References _, add_msg(), item_stack::begin(), Character::consume_items(), Character::crafting_inventory(), drain(), item_stack::empty(), vehicle_part::enabled, item_stack::end(), fuel_left(), get_avatar(), get_items(), read_only_visitable::has_charges(), is_crafting_component(), itype_detergent, itype_water, itype_water_clean, m_bad, m_good, name, and parts.

◆ use_harness()

void vehicle::use_harness ( int  part,
const tripoint pos 
)

Definition at line 1575 of file vehicle_use.cpp.

1576 {
1577  const vehicle_part &vp = parts[part];
1578  const vpart_info &vpi = vp.info();
1579 
1580  if( vp.is_unavailable() || vp.removed ) {
1581  debugmsg( "use_harness called on invalid part" );
1582  return;
1583  }
1584  if( !g->is_empty( pos ) ) {
1585  add_msg( m_info, _( "The harness is blocked." ) );
1586  return;
1587  }
1588  creature_tracker &creatures = get_creature_tracker();
1589  const std::function<bool( const tripoint & )> f = [&creatures]( const tripoint & pnt ) {
1590  monster *mon_ptr = creatures.creature_at<monster>( pnt );
1591  if( mon_ptr == nullptr ) {
1592  return false;
1593  }
1594  monster &f = *mon_ptr;
1595  return f.friendly != 0 && ( f.has_flag( mon_flag_PET_MOUNTABLE ) ||
1597  };
1598 
1599  const std::optional<tripoint> pnt_ = choose_adjacent_highlight(
1600  _( "Where is the creature to harness?" ), _( "There is no creature to harness nearby." ), f,
1601  false );
1602  if( !pnt_ ) {
1603  add_msg( m_info, _( "Never mind." ) );
1604  return;
1605  }
1606  const tripoint &target = *pnt_;
1607  monster *mon_ptr = creatures.creature_at<monster>( target );
1608  if( mon_ptr == nullptr ) {
1609  add_msg( m_info, _( "No creature there." ) );
1610  return;
1611  }
1612  monster &m = *mon_ptr;
1613  std::string Harness_Bodytype = "HARNESS_" + m.type->bodytype;
1614  if( m.friendly == 0 ) {
1615  add_msg( m_info, _( "This creature is not friendly!" ) );
1616  return;
1618  add_msg( m_info, _( "This creature cannot be harnessed." ) );
1619  return;
1620  } else if( !vpi.has_flag( Harness_Bodytype ) && !vpi.has_flag( "HARNESS_any" ) ) {
1621  add_msg( m_info, _( "The harness is not adapted for this creature morphology." ) );
1622  return;
1623  }
1624 
1625  m.add_effect( effect_harnessed, 1_turns, true );
1626  m.setpos( pos );
1627  //~ %1$s: monster name, %2$s: vehicle name
1628  add_msg( m_info, _( "You harness your %1$s to %2$s." ), m.get_name(), disp_name() );
1629  if( m.has_effect( effect_tied ) ) {
1630  add_msg( m_info, _( "You untie your %s." ), m.get_name() );
1632  if( m.tied_item ) {
1634  m.tied_item.reset();
1635  }
1636  }
1637 }
std::optional< tripoint > choose_adjacent_highlight(const std::string &message, const std::string &failure_message, const action_id action, const bool allow_vertical, const bool allow_autoselect)
Request player input of adjacent tile with highlighting, possibly on different z-level.
Definition: action.cpp:1212
item_location i_add(item it, bool should_stack=true, const item *avoid=nullptr, const item *original_inventory_item=nullptr, bool allow_drop=true, bool allow_wield=true, bool ignore_pkt_settings=false)
Adds the item to the character's worn items or wields it, or prompts if the Character cannot pick it ...
cata::value_ptr< item > tied_item
Definition: monster.h:529
bool has_flag(const mon_flag_id &f) const final
Definition: monster.cpp:1202
int friendly
Definition: monster.h:539
const mtype * type
Definition: monster.h:550
mon_flag_id mon_flag_PET_HARNESSABLE
Definition: mtype.cpp:127
mon_flag_id mon_flag_PET_MOUNTABLE
Definition: mtype.cpp:128
bodytype_id bodytype
Definition: mtype.h:355
static const efftype_id effect_tied("tied")
static const efftype_id effect_harnessed("harnessed")

References _, Creature::add_effect(), add_msg(), mtype::bodytype, choose_adjacent_highlight(), creature_tracker::creature_at(), debugmsg, disp_name(), effect_harnessed, effect_tied, monster::friendly, g, get_creature_tracker(), monster::get_name(), get_player_character(), Creature::has_effect(), monster::has_flag(), vpart_info::has_flag(), Character::i_add(), vehicle_part::info(), vehicle_part::is_unavailable(), m_info, mon_flag_PET_HARNESSABLE, mon_flag_PET_MOUNTABLE, part(), parts, pos, Creature::remove_effect(), vehicle_part::removed, Creature::setpos(), monster::tied_item, and monster::type.

◆ use_monster_capture()

void vehicle::use_monster_capture ( int  part,
const tripoint pos 
)

Definition at line 1559 of file vehicle_use.cpp.

1560 {
1561  if( parts[part].is_broken() || parts[part].removed ) {
1562  return;
1563  }
1564  item base = item( parts[part].get_base() );
1565  base.type->invoke( &get_avatar(), base, pos );
1566  if( base.has_var( "contained_name" ) ) {
1567  parts[part].set_flag( vp_flag::animal_flag );
1568  } else {
1569  parts[part].remove_flag( vp_flag::animal_flag );
1570  }
1571  parts[part].set_base( std::move( base ) );
1572  invalidate_mass();
1573 }
bool has_var(const std::string &name) const
Whether the variable is defined at all.
Definition: item.cpp:1928
const itype * type
Definition: item.h:3074
std::optional< int > invoke(Character *p, item &it, const tripoint &pos) const
Definition: itype.cpp:195

References animal_flag, get_avatar(), item::has_var(), invalidate_mass(), itype::invoke(), item, part(), parts, pos, and item::type.

◆ use_vehicle_tool()

bool vehicle::use_vehicle_tool ( vehicle veh,
const tripoint vp_pos,
const itype_id tool_type,
bool  no_invoke = false 
)
static

Definition at line 1781 of file vehicle_use.cpp.

1783 {
1784  item tool( tool_type, calendar::turn );
1785  const auto &[ammo_type_id, avail_ammo_amount] = veh.tool_ammo_available( tool_type );
1786  const int ammo_in_tool = veh.prepare_tool( tool );
1787  const bool is_battery_tool = !ammo_type_id.is_null() && ammo_type_id->ammo->type == ammo_battery;
1788  if( tool.ammo_required() > avail_ammo_amount ) {
1789  return false;
1790  }
1791  if( !no_invoke ) {
1792  get_player_character().invoke_item( &tool, vp_pos );
1793  }
1794 
1795  // HACK: Evil hack incoming
1797  if( act.id() == ACT_REPAIR_ITEM &&
1798  ( tool_type == itype_welder ||
1799  tool_type == itype_welder_crude ||
1800  tool_type == itype_welding_kit ||
1801  tool_type == itype_soldering_iron ||
1802  tool_type == itype_small_repairkit ||
1803  tool_type == itype_large_repairkit
1804  ) ) {
1805  act.index = INT_MIN; // tell activity the item doesn't really exist
1806  act.coords.push_back( vp_pos ); // tell it to search for the tool on `pos`
1807  act.str_values.push_back( tool_type.str() ); // specific tool on the rig
1808  }
1809 
1810  const int used_charges = ammo_in_tool - tool.ammo_remaining();
1811  if( used_charges > 0 ) {
1812  if( is_battery_tool ) {
1813  // if tool has less battery charges than it started with - discharge from vehicle batteries
1814  veh.discharge_battery( used_charges );
1815  } else {
1816  veh.drain( tool.ammo_current(), used_charges );
1817  }
1818  }
1819  return true;
1820 }
virtual bool invoke_item(item *, const tripoint &pt, int pre_obtain_moves=-1)
Asks how to use the item (if it has more than one use_method) and uses it.
Definition: character.cpp:7149
static activity_id act
Definition: sounds.cpp:79
static const itype_id itype_small_repairkit("small_repairkit")
static const activity_id ACT_REPAIR_ITEM("ACT_REPAIR_ITEM")
static const itype_id itype_large_repairkit("large_repairkit")
static const itype_id itype_soldering_iron("soldering_iron")
static const itype_id itype_welding_kit("welding_kit")
static const itype_id itype_welder_crude("welder_crude")
static const itype_id itype_welder("welder")

References act, ACT_REPAIR_ITEM, Character::activity, ammo_battery, item::ammo_current(), item::ammo_remaining(), item::ammo_required(), discharge_battery(), drain(), get_player_character(), string_id< T >::id(), Character::invoke_item(), itype_large_repairkit, itype_small_repairkit, itype_soldering_iron, itype_welder, itype_welder_crude, itype_welding_kit, prepare_tool(), string_id< T >::str(), tool_ammo_available(), and calendar::turn.

Referenced by hacksaw_activity_actor::do_turn().

◆ use_washing_machine()

void vehicle::use_washing_machine ( int  p)

Definition at line 1418 of file vehicle_use.cpp.

1419 {
1420  vehicle_part &vp = parts[p];
1421  avatar &player_character = get_avatar();
1422  // Get all the items that can be used as detergent
1423  const inventory &inv = player_character.crafting_inventory();
1424  std::vector<const item *> detergents = inv.items_with( [inv]( const item & it ) {
1425  return it.has_flag( STATIC( flag_id( "DETERGENT" ) ) ) && inv.has_charges( it.typeId(), 5 );
1426  } );
1427 
1428  vehicle_stack items = get_items( vp );
1429  bool filthy_items = std::all_of( items.begin(), items.end(), []( const item & i ) {
1430  return i.has_flag( json_flag_FILTHY );
1431  } );
1432 
1433  bool cbms = std::any_of( items.begin(), items.end(), []( const item & i ) {
1434  return i.is_bionic();
1435  } );
1436 
1437  if( vp.enabled ) {
1438  vp.enabled = false;
1439  add_msg( m_bad,
1440  _( "You turn the washing machine off before it's finished its cycle, and open its lid." ) );
1441  } else if( items.empty() ) {
1442  add_msg( m_bad, _( "The washing machine is empty; there's no point in starting it." ) );
1443  } else if( fuel_left( itype_water ) < 24 && fuel_left( itype_water_clean ) < 24 ) {
1444  add_msg( m_bad,
1445  _( "You need 24 charges of water in the tanks of the %s to fill the washing machine." ), name );
1446  } else if( detergents.empty() ) {
1447  add_msg( m_bad, _( "You need 5 charges of a detergent for the washing machine." ) );
1448  } else if( !filthy_items ) {
1449  add_msg( m_bad,
1450  _( "You need to remove all non-filthy items from the washing machine to start the washing program." ) );
1451  } else if( cbms ) {
1452  add_msg( m_bad, _( "CBMs can't be cleaned in a washing machine. You need to remove them." ) );
1453  } else {
1454  uilist detergent_selector;
1455  detergent_selector.text = _( "Use what detergent?" );
1456 
1457  std::vector<itype_id> det_types;
1458  for( const item *it : detergents ) {
1459  itype_id det_type = it->typeId();
1460  // If the vector does not contain the detergent type, add it
1461  if( std::find( det_types.begin(), det_types.end(), det_type ) == det_types.end() ) {
1462  det_types.emplace_back( det_type );
1463  }
1464 
1465  }
1466  int chosen_detergent = 0;
1467  // If there's a choice to be made on what detergent to use, ask the player
1468  if( det_types.size() > 1 ) {
1469  for( size_t i = 0; i < det_types.size(); ++i ) {
1470  detergent_selector.addentry( i, true, 0, item::nname( det_types[i] ) );
1471  }
1472  detergent_selector.addentry( UILIST_CANCEL, true, 0, _( "Cancel" ) );
1473  detergent_selector.query();
1474  chosen_detergent = detergent_selector.ret;
1475  }
1476 
1477  // If the player exits the menu, don't do anything else
1478  if( chosen_detergent == UILIST_CANCEL ) {
1479  return;
1480  }
1481 
1482  vp.enabled = true;
1483  for( item &n : items ) {
1484  n.set_age( 0_turns );
1485  }
1486 
1487  if( fuel_left( itype_water ) >= 24 ) {
1488  drain( itype_water, 24 );
1489  } else {
1490  drain( itype_water_clean, 24 );
1491  }
1492 
1493  std::vector<item_comp> detergent;
1494  detergent.emplace_back( det_types[chosen_detergent], 5 );
1495  player_character.consume_items( detergent, 1, is_crafting_component );
1496 
1497  add_msg( m_good,
1498  _( "You pour some detergent into the washing machine, close its lid, and turn it on. The washing machine is being filled from the water tanks." ) );
1499  }
1500 }
std::vector< const item * > items_with(const std::function< bool(const item &)> &filter) const
Definition: visitable.cpp:330
const int UILIST_CANCEL
Definition: ui.h:35

References _, add_msg(), uilist::addentry(), item_stack::begin(), Character::consume_items(), Character::crafting_inventory(), drain(), item_stack::empty(), vehicle_part::enabled, item_stack::end(), flag_id, fuel_left(), get_avatar(), get_items(), read_only_visitable::has_charges(), item::has_flag(), is_crafting_component(), visitable::items_with(), itype_water, itype_water_clean, m_bad, m_good, name, item::nname(), parts, uilist::query(), uilist::ret, STATIC, uilist::text, item::typeId(), and UILIST_CANCEL.

◆ valid_wheel_config()

bool vehicle::valid_wheel_config ( ) const

◆ velo_vec()

rl_vec2d vehicle::velo_vec ( ) const

Definition at line 1588 of file vehicle_move.cpp.

1589 {
1590  rl_vec2d ret;
1591  if( skidding ) {
1592  ret = move_vec();
1593  } else {
1594  ret = face_vec();
1595  }
1596  ret = ret.normalized();
1597  ret = ret * velocity;
1598  return ret;
1599 }

References face_vec(), move_vec(), cata::hash64_detail::ret, skidding, and velocity.

Referenced by map::vehicle_vehicle_collision().

◆ water_acceleration()

int vehicle::water_acceleration ( bool  fueled = true,
int  at_vel_in_vmi = -1 
) const

Definition at line 3783 of file vehicle.cpp.

3784 {
3785  if( !( engine_on || skidding ) ) {
3786  return 0;
3787  }
3788  int target_vmiph = std::max( at_vel_in_vmi, std::max( 1000,
3789  max_water_velocity( fueled ) / 4 ) );
3790  int cmps = vmiph_to_cmps( target_vmiph );
3791  double weight = to_kilogram( total_mass() );
3792  if( is_towing() ) {
3793  vehicle *other_veh = tow_data.get_towed();
3794  if( other_veh ) {
3795  weight = weight + to_kilogram( other_veh->total_mass() );
3796  }
3797  }
3798  int engine_power_ratio = units::to_watt( total_power( fueled ) ) / weight;
3799  int accel_at_vel = 100 * 100 * engine_power_ratio / cmps;
3800  add_msg_debug( debugmode::DF_VEHICLE, "%s: water accel at %d vimph is %d", name, target_vmiph,
3801  cmps_to_vmiph( accel_at_vel ) );
3802  return cmps_to_vmiph( accel_at_vel );
3803 }

References add_msg_debug, cmps_to_vmiph(), debugmode::DF_VEHICLE, engine_on, towing_data::get_towed(), is_towing(), max(), max_water_velocity(), name, skidding, units::to_kilogram(), units::to_watt(), total_mass(), total_power(), tow_data, and vmiph_to_cmps().

Referenced by acceleration(), and veh_interact::display_stats().

◆ water_draft()

double vehicle::water_draft ( ) const

water draft in meters - how much of the vehicle's body is under water must be less than the hull height or the boat will sink at some point, also add boats with deep draft running around

Definition at line 4341 of file vehicle.cpp.

4342 {
4343  if( coeff_water_dirty ) {
4344  coeff_water_drag();
4345  }
4346  return draft_m;
4347 }

References coeff_water_dirty, coeff_water_drag(), and draft_m.

Referenced by veh_interact::display_stats().

◆ water_hull_height()

double vehicle::water_hull_height ( ) const

watertight hull height in meters measures distance from bottom of vehicle to the point where the vehicle will start taking on water

Definition at line 4333 of file vehicle.cpp.

4334 {
4335  if( coeff_water_dirty ) {
4336  coeff_water_drag();
4337  }
4338  return hull_height;
4339 }

References coeff_water_dirty, coeff_water_drag(), and hull_height.

Referenced by veh_interact::display_stats().

◆ wheel_area()

int vehicle::wheel_area ( ) const

Calculates the sum of the area under the wheels of the vehicle.

Definition at line 4105 of file vehicle.cpp.

4106 {
4107  int total_area = 0;
4108  for( const int wheel_index : wheelcache ) {
4109  total_area += parts[wheel_index].info().wheel_info->contact_area;
4110  }
4111 
4112  return total_area;
4113 }

References parts, and wheelcache.

Referenced by veh_interact::display_stats(), overmap_ui::get_overmap_path_to(), and k_traction().

◆ would_install_prevent_flyable()

bool vehicle::would_install_prevent_flyable ( const vpart_info vpinfo,
const Character pc 
) const

Definition at line 4412 of file vehicle.cpp.

4413 {
4414  if( flyable && !rotors.empty() && !( vpinfo.has_flag( "SIMPLE_PART" ) ||
4415  vpinfo.has_flag( "AIRCRAFT_REPAIRABLE_NOPROF" ) ) ) {
4417  } else {
4418  return false;
4419  }
4420 }
static const proficiency_id proficiency_prof_aircraft_mechanic("prof_aircraft_mechanic")

References flyable, vpart_info::has_flag(), Character::has_proficiency(), proficiency_prof_aircraft_mechanic, and rotors.

Referenced by veh_interact::do_install().

◆ would_removal_prevent_flyable()

bool vehicle::would_removal_prevent_flyable ( const vehicle_part vp,
const Character pc 
) const

Definition at line 4438 of file vehicle.cpp.

4439 {
4440  if( flyable && !rotors.empty() && !vp.info().has_flag( "SIMPLE_PART" ) ) {
4442  } else {
4443  return false;
4444  }
4445 }

References flyable, vpart_info::has_flag(), Character::has_proficiency(), vehicle_part::info(), proficiency_prof_aircraft_mechanic, and rotors.

Referenced by can_do_activity_there(), and veh_interact::do_remove().

◆ would_repair_prevent_flyable()

bool vehicle::would_repair_prevent_flyable ( const vehicle_part vp,
const Character pc 
) const

Definition at line 4422 of file vehicle.cpp.

4423 {
4424  if( flyable && !rotors.empty() ) {
4425  if( vp.info().has_flag( "SIMPLE_PART" ) ||
4426  vp.info().has_flag( "AIRCRAFT_REPAIRABLE_NOPROF" ) ) {
4427  vpart_position vppos = vpart_position( const_cast<vehicle &>( *this ),
4428  index_of_part( const_cast<vehicle_part *>( &vp ) ) );
4429  return !vppos.is_inside();
4430  } else {
4432  }
4433  } else {
4434  return false;
4435  }
4436 }
bool is_inside() const
Definition: vehicle.cpp:7125

References flyable, vpart_info::has_flag(), Character::has_proficiency(), index_of_part(), vehicle_part::info(), vpart_position::is_inside(), proficiency_prof_aircraft_mechanic, and rotors.

Referenced by can_do_activity_there(), veh_interact::do_repair(), and veh_utils::most_repairable_part().

Member Data Documentation

◆ accessories

std::vector<int> vehicle::accessories

◆ active_autodrive_controller

std::shared_ptr<autodrive_controller> vehicle::active_autodrive_controller
private

Definition at line 2246 of file vehicle.h.

Referenced by do_autodrive(), get_debug_overlay_data(), and stop_autodriving().

◆ active_items

active_item_cache vehicle::active_items

◆ all_wheels_on_one_axis

bool vehicle::all_wheels_on_one_axis = false

Definition at line 2350 of file vehicle.h.

Referenced by is_wheel_state_correct_to_turn_on_rails(), and refresh().

◆ alternator_load

int vehicle::alternator_load = 0

◆ alternators

std::vector<int> vehicle::alternators

◆ anchor

safe_reference_anchor vehicle::anchor
private

Definition at line 2233 of file vehicle.h.

Referenced by get_safe_reference().

◆ autodrive_local_target

tripoint vehicle::autodrive_local_target = tripoint_zero
private

◆ autopilot_on

bool vehicle::autopilot_on = false

◆ avg_velocity

int vehicle::avg_velocity = 0

vehicle continuous moving average velocity see https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average alpha is 0.5: avg_velocity = avg_velocity + 0.5(velocity - avg_velocity) = 0.5 avg_velocity + 0.5 velocity

Definition at line 2282 of file vehicle.h.

Referenced by idle(), and smart_controller_handle_turn().

◆ batteries

std::vector<int> vehicle::batteries

◆ cable_ports

std::vector<int> vehicle::cable_ports

Definition at line 2196 of file vehicle.h.

Referenced by item::process_link(), refresh(), and item::reset_link().

◆ camera_on

bool vehicle::camera_on = false

◆ check_environmental_effects

bool vehicle::check_environmental_effects = false

Definition at line 2365 of file vehicle.h.

Referenced by gain_moves(), part_collision(), and refresh().

◆ coeff_air_changed

bool vehicle::coeff_air_changed = true
mutableprivate

◆ coeff_air_dirty

bool vehicle::coeff_air_dirty = true
mutableprivate

◆ coeff_rolling_dirty

bool vehicle::coeff_rolling_dirty = true
mutableprivate

Definition at line 2325 of file vehicle.h.

Referenced by coeff_rolling_drag(), enable_refresh(), invalidate_mass(), and suspend_refresh().

◆ coeff_water_dirty

bool vehicle::coeff_water_dirty = true
mutableprivate

◆ coefficient_air_resistance

double vehicle::coefficient_air_resistance = 1
mutableprivate

Definition at line 2107 of file vehicle.h.

Referenced by coeff_air_drag().

◆ coefficient_rolling_resistance

double vehicle::coefficient_rolling_resistance = 1
mutableprivate

Definition at line 2108 of file vehicle.h.

Referenced by coeff_rolling_drag().

◆ coefficient_water_resistance

double vehicle::coefficient_water_resistance = 1
mutableprivate

Definition at line 2109 of file vehicle.h.

Referenced by coeff_water_drag().

◆ collision_check_points

std::set<point> vehicle::collision_check_points

Definition at line 992 of file vehicle.h.

Referenced by get_debug_overlay_data(), immediate_path(), and stop_autodriving().

◆ control_req_parts

std::vector<int> vehicle::control_req_parts

Definition at line 2198 of file vehicle.h.

Referenced by can_control_in_air(), can_control_on_land(), and refresh().

◆ cruise_velocity

int vehicle::cruise_velocity = 0

◆ draft_m

double vehicle::draft_m = 1
mutableprivate

Definition at line 2110 of file vehicle.h.

Referenced by can_float(), coeff_water_drag(), and water_draft().

◆ edges

std::map<point, vpart_edge_info> vehicle::edges
private

Definition at line 2125 of file vehicle.h.

Referenced by refresh(), remove_fake_parts(), and update_active_fakes().

◆ emitters

std::vector<int> vehicle::emitters

Definition at line 2180 of file vehicle.h.

Referenced by idle(), and refresh().

◆ engine_on

bool vehicle::engine_on = false

◆ engines

std::vector<int> vehicle::engines

◆ extra_drag

units::power vehicle::extra_drag = 0_W

Definition at line 2298 of file vehicle.h.

Referenced by refresh(), static_drag(), and update_alternator_load().

◆ face

tileray vehicle::face

◆ fake_parts

std::vector<int> vehicle::fake_parts

◆ floating

std::vector<int> vehicle::floating

◆ flyable

bool vehicle::flyable = true
private

◆ front_left

point vehicle::front_left

Definition at line 2306 of file vehicle.h.

Referenced by immediate_path(), and refresh().

◆ front_right

point vehicle::front_right

Definition at line 2307 of file vehicle.h.

Referenced by immediate_path(), and refresh().

◆ fuel_containers

std::vector<int> vehicle::fuel_containers

Definition at line 2191 of file vehicle.h.

Referenced by fuel_left(), refresh(), and slow_leak().

◆ fuel_remainder

std::map<itype_id, units::energy> vehicle::fuel_remainder

Definition at line 2214 of file vehicle.h.

Referenced by consume_fuel().

◆ fuel_used_last_turn

std::map<itype_id, units::energy> vehicle::fuel_used_last_turn

Definition at line 2215 of file vehicle.h.

Referenced by consume_fuel(), gain_moves(), and print_fuel_indicators().

◆ funnels

std::vector<int> vehicle::funnels

Definition at line 2179 of file vehicle.h.

Referenced by refresh(), and update_time().

◆ has_enabled_smart_controller

bool vehicle::has_enabled_smart_controller = false

◆ hull_height

double vehicle::hull_height = 0.3
mutableprivate

Definition at line 2111 of file vehicle.h.

Referenced by can_float(), coeff_water_drag(), and water_hull_height().

◆ in_deep_water

bool vehicle::in_deep_water = false
mutableprivate

◆ in_water

bool vehicle::in_water = false
mutableprivate

Definition at line 2338 of file vehicle.h.

Referenced by check_falling_or_floating(), is_in_water(), and is_watercraft().

◆ insides_dirty

bool vehicle::insides_dirty = true

Definition at line 2367 of file vehicle.h.

Referenced by damage_direct(), open_or_close(), refresh(), and refresh_insides().

◆ is_alarm_on

bool vehicle::is_alarm_on = false

◆ is_autodriving

bool vehicle::is_autodriving = false

◆ is_falling

bool vehicle::is_falling = false

◆ is_flying

bool vehicle::is_flying = false
mutableprivate

◆ is_following

bool vehicle::is_following = false

◆ is_locked

bool vehicle::is_locked = false

◆ is_on_ramp

bool vehicle::is_on_ramp = false

◆ is_patrolling

bool vehicle::is_patrolling = false

◆ labels

std::set<label> vehicle::labels

◆ last_turn

units::angle vehicle::last_turn = 0_degrees

Definition at line 2293 of file vehicle.h.

Referenced by handbrake(), map::move_vehicle(), possibly_recover_from_skid(), stop(), and turn().

◆ last_update

time_point vehicle::last_update = calendar::before_time_starts

Definition at line 2266 of file vehicle.h.

Referenced by init_state(), place_appliance(), restore_folded_parts(), and update_time().

◆ linked_item_epower_this_turn

units::power vehicle::linked_item_epower_this_turn

◆ loose_parts

std::vector<int> vehicle::loose_parts

◆ loot_zones

std::unordered_multimap<point, zone_data> vehicle::loot_zones

◆ magic

bool vehicle::magic = false

◆ mass_cache

units::mass vehicle::mass_cache
mutableprivate

Definition at line 2234 of file vehicle.h.

Referenced by calc_mass_center(), and total_mass().

◆ mass_center_no_precalc

point vehicle::mass_center_no_precalc
mutableprivate

Definition at line 2243 of file vehicle.h.

Referenced by calc_mass_center(), and local_center_of_mass().

◆ mass_center_no_precalc_dirty

bool vehicle::mass_center_no_precalc_dirty = true
mutableprivate

◆ mass_center_precalc

point vehicle::mass_center_precalc
mutableprivate

Definition at line 2242 of file vehicle.h.

Referenced by calc_mass_center(), and rotated_center_of_mass().

◆ mass_center_precalc_dirty

bool vehicle::mass_center_precalc_dirty = true
mutableprivate

Definition at line 2322 of file vehicle.h.

Referenced by calc_mass_center(), enable_refresh(), invalidate_mass(), and suspend_refresh().

◆ mass_dirty

bool vehicle::mass_dirty = true
mutableprivate

◆ mount_max

point vehicle::mount_max
mutableprivate

◆ mount_min

point vehicle::mount_min
mutableprivate

Definition at line 2241 of file vehicle.h.

Referenced by coeff_air_drag(), coeff_water_drag(), refresh(), and set_tow_directions().

◆ move

tileray vehicle::move

◆ mufflers

std::vector<int> vehicle::mufflers

Definition at line 2193 of file vehicle.h.

Referenced by get_exhaust_part(), and refresh().

◆ name

std::string vehicle::name

Definition at line 2201 of file vehicle.h.

Referenced by act_on_map(), overmapbuffer::add_vehicle(), map::add_vehicle_to_map(), automatic_fire_turret(), break_off(), build_bike_rack_menu(), build_electronics_menu(), MapExtras::burned_ground_parser(), close(), doors::close_door(), coeff_air_drag(), collision(), veh_interact::complete_vehicle(), control_engines(), game::control_vehicle(), veh_app_interact::create_or_get_ui_adaptor(), damage_direct(), decrement_summon_timer(), map::detach_vehicle(), disp_name(), map::displace_vehicle(), veh_interact::display_name(), veh_interact::do_rename(), construct::done_vehicle(), drive_to_local_target(), game::exam_vehicle(), explode_fuel(), optional_vpart_position::extended_description(), vehicles::finalize_prototypes(), find_vehicles_to_rack(), find_vehicles_to_unrack(), bikerack_racking_activity_actor::finish(), bikerack_unracking_activity_actor::finish(), vehicle_folding_activity_actor::fold_vehicle(), get_folded_item(), game::grabbed_veh_move(), ground_acceleration(), handbrake(), handle_trap(), idle(), advanced_inv_area::init(), is_towed(), is_towing(), k_traction(), lift_thrust_of_rotorcraft(), item::link_to(), lock(), doors::lock_door(), max_ground_velocity(), max_water_velocity(), merge_appliance_into_grid(), merge_rackable_vehicle(), avatar_action::move(), map::move_vehicle(), game::moving_vehicle_dismount(), open(), open(), part_collision(), part_removal_cleanup(), pickveh(), place_appliance(), place_spawn_items(), pldrive(), possibly_recover_from_skid(), Character::pour_into(), power_parts(), game::print_vehicle_info(), process_vehicle_items(), put_into_vehicle(), advanced_inventory::query_destination(), advanced_inventory::redraw_pane(), veh_app_interact::remove(), remove_carried_vehicle(), remove_part(), veh_app_interact::rename(), veh_utils::repair_part(), separate_from_grid(), map::shake_vehicle(), shed_loose_parts(), slowdown(), split_vehicles(), start_engines(), activity_handlers::start_engines_finish(), thrust(), vehicle_unfolding_activity_actor::unfold_vehicle(), unlock(), doors::unlock_door(), update_time(), link_up_actor::use(), use_autoclave(), use_dishwasher(), use_washing_machine(), vehicle(), map::vehicle_vehicle_collision(), and water_acceleration().

◆ no_refresh

bool vehicle::no_refresh = false
private

Definition at line 2317 of file vehicle.h.

Referenced by enable_refresh(), refresh(), and suspend_refresh().

◆ occupied_cache_direction

units::angle vehicle::occupied_cache_direction = 0_degrees
mutableprivate

Definition at line 2116 of file vehicle.h.

Referenced by get_points().

◆ occupied_cache_pos

tripoint vehicle::occupied_cache_pos = { -1, -1, -1 }
mutableprivate

Definition at line 2114 of file vehicle.h.

Referenced by advance_precalc_mounts(), get_points(), and refresh().

◆ occupied_points

std::set<tripoint> vehicle::occupied_points
mutableprivate

Definition at line 2118 of file vehicle.h.

Referenced by get_points().

◆ of_turn

float vehicle::of_turn = 0.0f

◆ of_turn_carry

float vehicle::of_turn_carry = 0.0f

Definition at line 2297 of file vehicle.h.

Referenced by act_on_map(), gain_moves(), and stop().

◆ old_owner

faction_id vehicle::old_owner = faction_id::NULL_ID()

◆ om_id

int vehicle::om_id = 0

◆ owner

faction_id vehicle::owner = faction_id::NULL_ID()

◆ parts

std::vector<vehicle_part> vehicle::parts
private

Definition at line 2121 of file vehicle.h.

Referenced by activate_animal_follow(), activate_magical_follow(), active_reactor_epower(), advance_precalc_mounts(), all_parts_at_location(), assign_seat(), balanced_wheel_config(), basic_consumption(), battery_left(), battery_power_level(), break_off(), bub_part_pos(), build_interact_menu(), can_close(), can_control_in_air(), can_control_on_land(), can_enable(), can_mount(), can_unmount(), coeff_air_drag(), coeff_rolling_drag(), collision(), control_engines(), damage(), do_remove_part_actual(), drain(), drain_energy(), exhaust_dest(), find_and_split_vehicles(), find_lines_of_parts(), find_vehicles_to_unrack(), fuel_capacity(), fuel_items_left(), fuel_left(), fuel_usage(), fuels_left(), get_bounding_box(), get_display_of_tile(), get_edge_info(), get_exhaust_part(), get_folded_item(), get_harnessed_animal(), get_non_fake_part(), get_passenger(), get_remote_part(), global_part_pos3(), has_available_electric_engine(), has_engine_conflict(), has_engine_type(), has_engine_type_not(), idle(), index_of_part(), init_state(), install_part(), invalidate_towing(), is_alternator_on(), is_connected(), level_vehicle(), lift_thrust_of_rotorcraft(), lights(), lock_or_unlock(), max_reactor_epower(), merge_rackable_vehicle(), merge_vehicle_parts(), next_part_to_close(), next_part_to_lock(), next_part_to_open(), next_part_to_unlock(), noise_and_smoke(), open_all_at(), open_or_close(), part(), part_base(), part_collision(), part_count(), part_count_real(), part_count_real_cached(), part_displayed_at(), part_has_lock(), part_removal_cleanup(), parts_at_relative(), place_spawn_items(), power_parts(), precalc_mounts(), precalculate_vehicle_turning(), precollision_check(), print_fuel_indicators(), print_part_list(), print_vparts_descs(), real_parts(), refresh(), refresh_pivot(), remove_carried_vehicle(), remove_fake_parts(), remove_part(), restore_folded_parts(), roof_at_part(), set_tow_directions(), shift_if_needed(), shift_parts(), slow_leak(), smart_controller_handle_turn(), smash(), split_vehicles(), start_engines(), steering_effectiveness(), stop_engines(), thrust(), total_accessory_epower(), total_alternator_epower(), total_engine_epower(), total_power(), total_solar_epower(), total_water_wheel_epower(), total_wind_epower(), turrets(), turrets_set_mode(), turrets_set_targeting(), unlink_cables(), unlock(), update_active_fakes(), update_alternator_load(), update_time(), use_autoclave(), use_dishwasher(), use_harness(), use_monster_capture(), use_washing_machine(), and wheel_area().

◆ pivot_anchor

std::array<point, 2> vehicle::pivot_anchor

◆ pivot_cache

point vehicle::pivot_cache
mutableprivate

Definition at line 2236 of file vehicle.h.

Referenced by pivot_point(), and refresh_pivot().

◆ pivot_dirty

bool vehicle::pivot_dirty = true
mutableprivate

Definition at line 2320 of file vehicle.h.

Referenced by damage_direct(), invalidate_mass(), pivot_point(), and refresh_pivot().

◆ pivot_rotation

std::array<units::angle, 2> vehicle::pivot_rotation = { { 0_degrees, 0_degrees } }

◆ planters

std::vector<int> vehicle::planters

Definition at line 2194 of file vehicle.h.

Referenced by idle(), and refresh().

◆ pos

point vehicle::pos = point_zero

◆ precollision_on

bool vehicle::precollision_on = true

Definition at line 2361 of file vehicle.h.

Referenced by precollision_check(), and toggle_autopilot().

◆ rail_wheel_bounding_box

bounding_box vehicle::rail_wheel_bounding_box

Definition at line 2305 of file vehicle.h.

Referenced by is_wheel_state_correct_to_turn_on_rails(), and refresh().

◆ rail_wheelcache

std::vector<int> vehicle::rail_wheelcache

◆ reactors

std::vector<int> vehicle::reactors

◆ relative_parts

std::map<point, std::vector<int> > vehicle::relative_parts

Definition at line 2209 of file vehicle.h.

Referenced by exhaust_dest(), get_edge_info(), get_points(), parts_at_relative(), and refresh().

◆ requested_z_change

int vehicle::requested_z_change = 0
private

Definition at line 2342 of file vehicle.h.

Referenced by act_on_map(), get_z_change(), and thrust().

◆ rotors

std::vector<int> vehicle::rotors

◆ sails

std::vector<int> vehicle::sails

Definition at line 2178 of file vehicle.h.

Referenced by refresh().

◆ skidding

bool vehicle::skidding = false

◆ sm_pos

tripoint vehicle::sm_pos = tripoint_zero

Submap coordinates of the currently loaded submap (see game::m) that contains this vehicle.

These values are changed when the map shifts (but the vehicle is not actually moved than, it also stays on the same submap, only the relative coordinates in map::grid have changed). These coordinates must always refer to the submap in map::grid that contains this vehicle. When the vehicle is really moved (by map::displace_vehicle), set_submap_moved is called and updates these values, when the map is only shifted or when a submap is loaded into the map the values are directly set. The vehicles position does not change therefore no call to set_submap_moved is required.

Definition at line 2261 of file vehicle.h.

Referenced by act_on_map(), map::add_vehicle(), check_heli_ascend(), map::detach_vehicle(), global_pos3(), map::loadn(), merge_rackable_vehicle(), map::move_vehicle(), on_move(), open_or_close(), part_collision(), game::place_vehicle_nearby(), precollision_check(), remove_part(), set_submap_moved(), split_vehicles(), update_time(), and map::vehicle_vehicle_collision().

◆ smart_controller_cfg

std::optional<smart_controller_config> vehicle::smart_controller_cfg = std::nullopt

Definition at line 2226 of file vehicle.h.

Referenced by build_interact_menu(), and smart_controller_handle_turn().

◆ smart_controller_state

std::optional<smart_controller_cache> vehicle::smart_controller_state = std::nullopt

Definition at line 2224 of file vehicle.h.

Referenced by refresh(), and smart_controller_handle_turn().

◆ solar_panels

std::vector<int> vehicle::solar_panels

◆ speciality

std::vector<int> vehicle::speciality

Definition at line 2188 of file vehicle.h.

Referenced by has_security_working(), refresh(), and smash_security_system().

◆ steering

std::vector<int> vehicle::steering

◆ summon_time_limit

std::optional<time_duration> vehicle::summon_time_limit = std::nullopt

Definition at line 2221 of file vehicle.h.

Referenced by decrement_summon_timer().

◆ tags

std::set<std::string> vehicle::tags

Definition at line 2211 of file vehicle.h.

Referenced by add_tag(), has_tag(), and player_in_control().

◆ theft_time

std::optional<time_point> vehicle::theft_time

Definition at line 2300 of file vehicle.h.

Referenced by handle_potential_theft(), remove_old_owner(), and set_old_owner().

◆ tow_data

towing_data vehicle::tow_data

◆ tracking_on

bool vehicle::tracking_on = false

◆ turn_dir

units::angle vehicle::turn_dir = 0_degrees

◆ turret_locations

std::vector<int> vehicle::turret_locations

Definition at line 2192 of file vehicle.h.

Referenced by refresh(), and turrets().

◆ type

vproto_id vehicle::type

Type of the vehicle as it was spawned.

This will never change, but it can be an invalid type (e.g. if the definition of the prototype has been removed from json or if it has been spawned with the default constructor).

Definition at line 2207 of file vehicle.h.

Referenced by map::add_vehicle_to_map(), damage(), damage_all(), damage_direct(), explode_fuel(), vehicles::finalize_prototypes(), install_part(), part_collision(), place_spawn_items(), place_zones(), print_speed_gauge(), remove_part(), spew_field(), use_charges(), and vehicle().

◆ vehicle_noise

unsigned char vehicle::vehicle_noise = 0

Definition at line 2374 of file vehicle.h.

Referenced by noise_and_smoke(), sounds::process_sound_markers(), and stop_engines().

◆ velocity

int vehicle::velocity = 0

◆ vertical_velocity

int vehicle::vertical_velocity = 0

◆ water_wheels

std::vector<int> vehicle::water_wheels

◆ wheelcache

std::vector<int> vehicle::wheelcache

◆ wind_turbines

std::vector<int> vehicle::wind_turbines

◆ zones_dirty

bool vehicle::zones_dirty = true

The documentation for this class was generated from the following files: